@deftai/directive-content 0.92.0 → 0.93.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.
@@ -18,6 +18,52 @@ Epic spine: [#2874](https://github.com/deftai/directive/issues/2874). This doc i
18
18
 
19
19
  If you are installing Directive for the first time, start at [QUICK-START.md](../QUICK-START.md) or [getting-started.md](./getting-started.md), then return here for host-specific expectations.
20
20
 
21
+ Native **file-host** slash/prompt command registration (thin wrappers under `.claude/commands/`, `.cursor/commands/`, and peers) is documented in [slash-multi-host.md](./slash-multi-host.md) (epic #55). **OpenClaw L2 product commands** are a separate skills adapter ([#3064](https://github.com/deftai/directive/issues/3064)) — see § L2 product commands below. That surface is separate from always-pin skills (#3001/#3008), spawn/review mapping, and skill-discovery residual [#75](https://github.com/deftai/directive/issues/75).
22
+
23
+ ---
24
+
25
+ ## L2 product commands (OpenClaw adapter — #3064)
26
+
27
+ OpenClaw does **not** load repo-local command files the way Claude/Cursor do. L2 parity for the **exactly 13** product commands is delivered as **thin user-invocable skills** deposited into the OpenClaw **main workspace skills** root (real copies — not symlink-escape into npm; same spirit as always-pins).
28
+
29
+ ### Hybrid layout (LockedDecisions D1–D3)
30
+
31
+ | Artifact | OpenClaw slug | Role |
32
+ |----------|---------------|------|
33
+ | **Router** | `deft` | Preferred **native/menu-facing** entry (Telegram `BOT_COMMANDS` budget) |
34
+ | **13 product skills** | e.g. `deft_run_interview`, `deft_continue` | Invocable as `/<slug>` text skills for discoverability |
35
+
36
+ Stable map (logical slash → OpenClaw slug, `a-z0-9_`, max 32). Colons never appear in OC slugs. Example: `/deft:directive:run:interview` → `deft_run_interview`. Full table lives in `packages/core/src/slash/openclaw-slugs.ts` and is unit-tested for bijectivity against `listProductCommands()`.
37
+
38
+ Bodies stay **thin** (L5): frontmatter + short dispatch pointer to the same content-relative targets as file hosts (`generateThinWrappers()` IR). ⊗ Inline full strategy/skill bodies. ⊗ Add `openclaw` to `HOST_COMMAND_LAYOUTS` / invent `.openclaw/commands/`.
39
+
40
+ ### Native menu / `commands.nativeSkills` (D3)
41
+
42
+ | Setting | Expected behavior |
43
+ |---------|-------------------|
44
+ | Prefer menu safety | Use the **`deft` router** as the primary bot menu entry; invoke product work via router args or typed `/deft_run_*` skill text |
45
+ | `commands.nativeSkills` **on** / aggressive native registration | All `user-invocable: true` skills (router + 13 + always-pins) **may** flood Telegram → `BOT_COMMANDS_TOO_MUCH` risk |
46
+ | `auto` / selective | Prefer **router-first** for menu slots; keep the 13 invocable as skill/text without requiring 13 menu slots |
47
+ | **off** | Skills remain loadable; operators type skill names / prose — no native menu flood |
48
+
49
+ ! Do not require 13 Telegram bot menu slots for L2 parity.
50
+
51
+ ### Wire path (D4–D5)
52
+
53
+ 1. **Primary recovery:** `deft doctor --fix` when OpenClaw is detected — deposits managed L2 skills next to always-pins.
54
+ 2. **init/update:** deposits when OpenClaw signals are present and `plan.policy.openClawProductCommands` is not false. **Fail-closed** when OpenClaw is not detected (no writes on non-OC machines).
55
+ 3. Multi-seat: `deft doctor --fix --openclaw-all-agents` (same flag as always-pins).
56
+ 4. Opt-out: `plan.policy.openClawProductCommands: false` — removes **managed** L2 thin skills only; preserves consumer custom skills at the same slug.
57
+ 5. After deposit: **restart the OpenClaw gateway or start a new session** so `available_skills` refreshes.
58
+
59
+ Always-pin skills (`deft-directive-build`, `pre-pr`, `review-cycle`, `swarm`) remain a **different** surface from L2 product commands (`/deft:directive:run:interview`, `/deft:continue`, …).
60
+
61
+ Inspect policy:
62
+
63
+ ```bash
64
+ deft policy:show --field=openClawProductCommands
65
+ ```
66
+
21
67
  ---
22
68
 
23
69
  ## Mental model (host class)
@@ -0,0 +1,84 @@
1
+ # Multi-host skill discovery (#75)
2
+
3
+ Directive deposits **thin skill discovery pointers** so agent hosts that do not
4
+ scan `.agents/skills/` still auto-load the same consumer skill inventory.
5
+
6
+ ## Canonical vs additional paths
7
+
8
+ | Path | Role |
9
+ |------|------|
10
+ | `.agents/skills/` | **Canonical** consumer discovery (landed with #94 / install `writeAgentsSkills`) |
11
+ | `.claude/skills/` | Claude Code |
12
+ | `.codex/skills/` | OpenAI Codex |
13
+ | `.github/skills/` | GitHub Copilot |
14
+ | `.cursor/skills/` | Cursor (when not fully covered by optional OpenPackage install) |
15
+
16
+ Additional host paths **mirror** the same thin `SKILL.md` inventory as
17
+ `.agents/skills/`. They do not fork independent skill bodies. Full skill text
18
+ lives under `.deft/core/skills/…` (or `.deft/core/SKILL.md` for the root
19
+ `deft` skill).
20
+
21
+ ## Thin pointers only
22
+
23
+ Each deposited `SKILL.md` is a short frontmatter + `Read and follow: .deft/core/…`
24
+ line. Init/update **must not** copy full skill process docs into host skill dirs
25
+ (those rot on framework upgrade).
26
+
27
+ Windows: deposit uses ordinary file writes (contained projection). Elevated
28
+ symlinks are **not** required.
29
+
30
+ ## When deposit runs
31
+
32
+ - `directive init` / greenfield scaffold — after `.agents/skills/`
33
+ - `directive update` / refresh — every refresh (idempotent rewrite of managed
34
+ pointers when content drifts)
35
+
36
+ ## Per-host opt-out
37
+
38
+ Typed policy: `plan.policy.hostSkillDiscovery`
39
+
40
+ ```json
41
+ {
42
+ "plan": {
43
+ "policy": {
44
+ "hostSkillDiscovery": {
45
+ "claude": true,
46
+ "cursor": true,
47
+ "codex": true,
48
+ "github": false
49
+ }
50
+ }
51
+ }
52
+ }
53
+ ```
54
+
55
+ - Default: all four residual hosts **enabled**
56
+ - Inspect: `deft policy:show --field=hostSkillDiscovery`
57
+ - Opt-out skips deposit for that host only (does not remove unrelated user files)
58
+
59
+ Distinct from `plan.policy.hostHooks` (hook JSON deposit, #2752).
60
+
61
+ ## Relationship to #55 slash registration
62
+
63
+ | | **#75 skill discovery** | **#55 slash / commands** |
64
+ |--|-------------------------|---------------------------|
65
+ | Artifact | Host **skill** dirs (`…/skills/`) | Host **command/prompt** files (`…/commands/`, `…/prompts/`) |
66
+ | Product set | Existing consumer skill inventory | Locked product slash set (L2) |
67
+ | Content | Thin skill pointer `SKILL.md` | Thin command wrapper (~40–100 tok) |
68
+ | Deposit | This doc / `skill-discovery-deposit` | Epic children #3052–#3055 |
69
+
70
+ Do **not** treat slash completion as closing skill-path residual, or skill
71
+ deposit as registering slash commands.
72
+
73
+ ## Relationship to OpenPackage
74
+
75
+ OpenPackage (#2462 / #2370) is an optional tiered pack install for some hosts.
76
+ It does **not** replace init/update multi-host skill discovery for the residual
77
+ matrix above. Close #75 only when residual host paths are deposited (or
78
+ explicitly opted out), not solely because OpenPackage exists.
79
+
80
+ ## Implementation pointers
81
+
82
+ - Layouts + policy: `packages/core/src/init-deposit/skill-discovery-hosts.ts`
83
+ - Deposit: `packages/core/src/init-deposit/skill-discovery-deposit.ts`
84
+ - Shared inventory with `.agents/skills/`: `CONSUMER_SKILL_DISCOVERY_INVENTORY`
@@ -0,0 +1,241 @@
1
+ # Multi-host native slash-command registration
2
+
3
+ Operator guide for **host-native** Directive slash and prompt files after epic [#55](https://github.com/deftai/directive/issues/55).
4
+
5
+ This surface is **not** skill auto-discovery ([#75](https://github.com/deftai/directive/issues/75)). Skills stay under skill deposit paths. Slash registration writes thin command/prompt wrappers so hosts can show `/deft…` (or the host equivalent) in autocomplete.
6
+
7
+ Legend (RFC2119): `!`=MUST, `~`=SHOULD, `≉`=SHOULD NOT, `⊗`=MUST NOT, `?`=MAY.
8
+
9
+ Product locks: **LockedDecisions L1–L10** on [#55](https://github.com/deftai/directive/issues/55). Code waves: [#3052](https://github.com/deftai/directive/issues/3052) generator, [#3053](https://github.com/deftai/directive/issues/3053) emitters, [#3054](https://github.com/deftai/directive/issues/3054) deposit. This page is the docs/dogfood child [#3055](https://github.com/deftai/directive/issues/3055).
10
+
11
+ Prose SoT for routing and deprecation aliases: [commands.md § Slash Command Namespaces](../commands.md#slash-command-namespaces-418--1670).
12
+
13
+ ---
14
+
15
+ ## What you get
16
+
17
+ On `directive init` and `deft update`, Directive deposits **exactly 13** thin wrappers (L2) for every **enabled** host that has a real emitter (L6).
18
+
19
+ | Host id | Directory | Surface |
20
+ |---------|-----------|---------|
21
+ | `claude` | `.claude/commands/` | commands |
22
+ | `cursor` | `.cursor/commands/` | commands |
23
+ | `grok` | `.grok/commands/` | commands |
24
+ | `codex` | `.codex/prompts/` | prompts |
25
+ | **OpenClaw** (adapter, not file emitter) | OpenClaw **workspace skills** (`~/.openclaw/workspace/skills` or `$OPENCLAW_STATE_DIR/...`) | user-invocable skills + router |
26
+
27
+ File hosts use portable hyphen filenames (L4), for example `deft-directive-run-interview.md` and `deft-continue.md`. Logical slash ids keep the namespace form (`/deft:directive:run:interview`).
28
+
29
+ **OpenClaw** is **not** a fifth row in `SLASH_EMITTER_HOSTS` / `HOST_COMMAND_LAYOUTS`. There is no project-tree `.openclaw/commands/` deposit (that would be stub theater — Gateway does not load that path). OpenClaw L2 parity ships as a **skills/plugin adapter** ([#3064](https://github.com/deftai/directive/issues/3064)): thin **user-invocable** skills under the main workspace skills root, with a stable `logicalId → openClawSlug` map (`a-z0-9_`, max 32). See [openclaw-agent-host.md](./openclaw-agent-host.md) § L2 product commands.
30
+
31
+ ⊗ Treat last-writer-wins single-host install as the product default. One repo may use many hosts; deposit targets the **configured set** in one pass.
32
+
33
+ ---
34
+
35
+ ## Product set (L2 — exactly 13)
36
+
37
+ | # | Logical slash id | Filename stem |
38
+ |---|------------------|---------------|
39
+ | 1 | `/deft:directive:change` | `deft-directive-change` |
40
+ | 2 | `/deft:directive:change:apply` | `deft-directive-change-apply` |
41
+ | 3 | `/deft:directive:change:verify` | `deft-directive-change-verify` |
42
+ | 4 | `/deft:directive:change:archive` | `deft-directive-change-archive` |
43
+ | 5 | `/deft:directive:run:interview` | `deft-directive-run-interview` |
44
+ | 6 | `/deft:directive:run:yolo` | `deft-directive-run-yolo` |
45
+ | 7 | `/deft:directive:run:map` | `deft-directive-run-map` |
46
+ | 8 | `/deft:directive:run:discuss` | `deft-directive-run-discuss` |
47
+ | 9 | `/deft:directive:run:research` | `deft-directive-run-research` |
48
+ | 10 | `/deft:directive:run:speckit` | `deft-directive-run-speckit` |
49
+ | 11 | `/deft:directive:run:probe` | `deft-directive-run-probe` |
50
+ | 12 | `/deft:continue` | `deft-continue` |
51
+ | 13 | `/deft:checkpoint` | `deft-checkpoint` |
52
+
53
+ ⊗ Auto-register every `deft-directive-*` skill as a slash entry.
54
+ ⊗ Expand N without an amendment to L2 on #55.
55
+
56
+ Legacy prose aliases (`/deft:change`, `/deft:run:…`) remain accepted in agent text with deprecation guidance. Native host files emit **canonical names only** (L3) — no second set of alias files.
57
+
58
+ ---
59
+
60
+ ## Thin wrappers (L5)
61
+
62
+ Each managed file is a short pointer, not a copy of a strategy or skill:
63
+
64
+ - YAML frontmatter: `description` (and `argument-hint` when needed)
65
+ - Body: load the content-relative target under `.deft/core/` when installed; honor `$ARGUMENTS`; do not inline the target body
66
+
67
+ Token intent (catalog ≤ ~1k tok for the set; invoke body ~40–100 tok). Real cost is the strategy/skill after invoke.
68
+
69
+ Contributors: keep wrappers thin. Emitters consume `generateThinWrappers()` / `listProductCommands()` — do not maintain a second name table.
70
+
71
+ ---
72
+
73
+ ## Policy opt-out (`plan.policy.hostSlashCommands`)
74
+
75
+ Default: all emitter hosts enabled (`claude`, `cursor`, `grok`, `codex`).
76
+
77
+ Set a host to `false` in `xbrief/PROJECT-DEFINITION.xbrief.json` (or consumer deposit layout) to skip that host:
78
+
79
+ ```json
80
+ {
81
+ "plan": {
82
+ "policy": {
83
+ "hostSlashCommands": {
84
+ "claude": true,
85
+ "cursor": true,
86
+ "grok": false,
87
+ "codex": true
88
+ }
89
+ }
90
+ }
91
+ }
92
+ ```
93
+
94
+ Inspect:
95
+
96
+ ```bash
97
+ deft policy:show --field=hostSlashCommands
98
+ ```
99
+
100
+ On opt-out, init/update **removes only** Directive-managed thin wrappers for that host. Consumer-customized files at the same path are left alone. Unknown host keys fail validation.
101
+
102
+ This policy is parallel to `plan.policy.hostHooks` (enforcement hooks). Hooks and slash deposit are separate surfaces.
103
+
104
+ ### OpenClaw adapter opt-out (`plan.policy.openClawProductCommands`)
105
+
106
+ OpenClaw L2 deposit is **separate** from the four file emitters. Default **on** when the adapter is real and OpenClaw is detected.
107
+
108
+ ```json
109
+ {
110
+ "plan": {
111
+ "policy": {
112
+ "openClawProductCommands": false
113
+ }
114
+ }
115
+ }
116
+ ```
117
+
118
+ ```bash
119
+ deft policy:show --field=openClawProductCommands
120
+ ```
121
+
122
+ When false, init/update/doctor **removes only** Directive-managed OpenClaw L2 thin skills (router + 13 product slugs). Consumer-customized skills at the same slug are left alone. Deposit **does not write** OpenClaw artifacts when OpenClaw is not detected (fail-closed).
123
+
124
+ Primary recovery: `deft doctor --fix` (optional `--openclaw-all-agents` for multi-seat).
125
+
126
+ ---
127
+
128
+ ## Git policy (L8 — prefer commit)
129
+
130
+ ! **Prefer committing** managed product command/prompt files so every clone and every host share the same `/deft…` surface.
131
+
132
+ - Managed paths are exact product filenames (installer allowlist), not “claim the whole `.claude/commands/` tree.”
133
+ - Custom files you add next to managed ones stay app-owned.
134
+ - Idempotent rewrite on init/update keeps managed thin wrappers current either way.
135
+
136
+ ? Personal gitignore of host command dirs remains an escape for machine-local only setups. That is **not** the default team recommendation. Multi-host shared repos benefit most from a committed deposit.
137
+
138
+ ⊗ Do not use single-host last-writer-wins as the team sharing model.
139
+
140
+ ---
141
+
142
+ ## Prose fallback (L9)
143
+
144
+ File hosts without native registration (or with all file hosts opted out) still use the agent text convention in [commands.md](../commands.md). AGENTS.md and skills routing continue to work without native autocomplete files.
145
+
146
+ **OpenClaw** after [#3064](https://github.com/deftai/directive/issues/3064): when the adapter has deposited L2 skills, operators should prefer the invocable skills / router — not prose-only discovery. Prose `/deft:directive:…` remains accepted in agent text when skills are not yet wired (doctor not run, policy off, or host without OpenClaw signals).
147
+
148
+ ---
149
+
150
+ ## Slash registration vs skill discovery (#55 vs #75 vs #3064)
151
+
152
+ | Concern | Tracker | What lands |
153
+ |---------|---------|------------|
154
+ | Native slash / prompt **command files** | #55 | Thin wrappers under host command/prompt dirs; multi-host deposit |
155
+ | Skill auto-discovery paths | #75 | `SKILL.md` discovery under `.agents/skills/`, `.claude/skills/`, etc. |
156
+ | OpenClaw L2 product commands | #3064 | Thin **user-invocable** skills + router in OpenClaw workspace skills (not a file emitter) |
157
+
158
+ ! Do not treat skill discovery alone as “slash registration done.”
159
+ ! Do not dual-maintain full skill bodies as command file contents (L7).
160
+ ! Do not invent project `.openclaw/commands/` for L2 parity.
161
+
162
+ Agent-host runtime notes (OpenClaw spawn/review + L2 skills) live under [openclaw-agent-host.md](./openclaw-agent-host.md).
163
+
164
+ ---
165
+
166
+ ## Dogfood checklist (multi-host clone)
167
+
168
+ Use this after install or upgrade when two or more hosts share one repo.
169
+
170
+ 1. **Upgrade / deposit**
171
+
172
+ ```bash
173
+ npm i -g @deftai/directive@latest # when using the npm channel
174
+ directive update # or directive init on a new project
175
+ ```
176
+
177
+ 2. **Confirm policy**
178
+
179
+ ```bash
180
+ deft policy:show --field=hostSlashCommands
181
+ ```
182
+
183
+ Expect enabled hosts = emitters you want (default: all four true).
184
+
185
+ 3. **Smoke paths on disk** (enabled hosts only)
186
+
187
+ ```text
188
+ .claude/commands/deft-continue.md
189
+ .cursor/commands/deft-continue.md
190
+ .grok/commands/deft-continue.md
191
+ .codex/prompts/deft-continue.md
192
+ ```
193
+
194
+ Spot-check count: **13** managed files per enabled host. Bodies stay short (description + dispatch pointer).
195
+
196
+ 4. **Two-host UI check**
197
+
198
+ - Open the same clone in host A (for example Claude Code) and host B (for example Cursor).
199
+ - Type `/` (or the host prompt picker) and confirm Directive entries such as `deft-directive-run-interview` / `/deft:continue` appear on **both** hosts when both are enabled.
200
+ - Invoke one strategy command and one session command; agent should load the pointed strategy/resilience doc, not a fat inlined body.
201
+
202
+ 5. **Opt-out smoke (optional)**
203
+
204
+ - Set one host to `false`, run `directive update`, confirm that host’s **managed** product files were removed and other hosts remain.
205
+ - Restore `true` and update again to redeposit.
206
+
207
+ 6. **Git**
208
+
209
+ - Stage managed product paths (or let the installer staging path include them) and commit so teammates inherit the surface.
210
+ - ~ Avoid gitignoring the whole host command directory on team repos.
211
+
212
+ 7. **Hooks still separate**
213
+
214
+ - `deft verify:hooks-installed --scope=agent` checks hooks, not slash files.
215
+ - Missing autocomplete after a clean deposit is a host UI/cache issue or policy opt-out — re-run update and re-check policy before filing a deposit bug.
216
+
217
+ ---
218
+
219
+ ## Related surfaces
220
+
221
+ | Surface | Role |
222
+ |---------|------|
223
+ | [commands.md § Slash Command Namespaces](../commands.md#slash-command-namespaces-418--1670) | Prose namespaces, routing, deprecation aliases, deposit pointer |
224
+ | `packages/core/src/slash/` | Generator IR + emitters + OpenClaw adapter (maintainers) |
225
+ | `writeSlashCommandDeposit` | init/update file-host deposit |
226
+ | `depositOpenClawL2ProductCommands` / doctor OpenClaw L2 check | OpenClaw skills adapter (#3064) |
227
+ | `plan.policy.openClawProductCommands` | OpenClaw L2 adapter opt-out |
228
+ | `plan.policy.hostHooks` | Host enforcement hooks (#2438) — not slash files |
229
+ | [#75](https://github.com/deftai/directive/issues/75) | Skill discovery residual |
230
+ | [#3064](https://github.com/deftai/directive/issues/3064) | OpenClaw L2 product-command adapter |
231
+
232
+ ---
233
+
234
+ ## Design reading order (#55)
235
+
236
+ 1. LockedDecisions L1–L10 on #55
237
+ 2. Multi-host deposit amendment on #55
238
+ 3. Token / context design rules on #55
239
+ 4. This page + `commands.md`
240
+
241
+ Issue body (2026-03) on #55 is historical intent only.
package/main.md CHANGED
@@ -32,6 +32,7 @@ Legend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY.
32
32
  - Interfaces: [interfaces/cli.md](./content/interfaces/cli.md), [interfaces/tui.md](./content/interfaces/tui.md), [interfaces/web.md](./content/interfaces/web.md), [interfaces/rest.md](./content/interfaces/rest.md)
33
33
  - Tools: [tools/taskfile.md](./content/tools/taskfile.md), [scm/git.md](./content/scm/git.md), [scm/github.md](./content/scm/github.md), [tools/telemetry.md](./content/tools/telemetry.md)
34
34
  - Testing: [coding/testing.md](./content/coding/testing.md)
35
+ - Review process: [coding/review.md](./content/coding/review.md) (tool-agnostic; Greptile adapter via review-cycle skill)
35
36
 
36
37
  **Advanced:**
37
38
  - Contracts: [contracts/hierarchy.md](./content/contracts/hierarchy.md), [contracts/boundary-maps.md](./content/contracts/boundary-maps.md)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deftai/directive-content",
3
- "version": "0.92.0",
3
+ "version": "0.93.0",
4
4
  "description": "Shippable Directive framework content in the consumer .deft/core/ layout (C1 flatten), plus the engine surfaces (.githooks/, Taskfile.yml, tasks/) the deposit wires. Python-free per #2022 Phase 3. Refs #11, #1669, #1967.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -65,7 +65,7 @@
65
65
  "domain": "coding",
66
66
  "text": "All *.md in `docs/` directory (except README.md, AGENTS.md, WARP.md)",
67
67
  "path": "coding/coding.md",
68
- "body": "\n# Coding Guidelines\n\nSoftware development specific guidelines for AI agents.\n\nLegend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY.\n\n**⚠️ See also** (load only when needed):\n- [../main.md](../../main.md) - General AI behavior and agent persona\n- [PROJECT.md](../../PROJECT.md) - For project-specific overrides\n- [../tools/telemetry.md](../tools/telemetry.md) - When implementing logging/tracing/metrics\n\n## Code Organization\n\n**Documentation:**\n- ! All *.md in `docs/` directory (except README.md, AGENTS.md, WARP.md)\n- ! Prior tasks/plans in `history/`\n\n**Filenames:**\n- ~ Use hyphens not underscores (unless language idiom)\n\n**Secrets:**\n- ! ALL secrets in `secrets/` dir as .env files\n- ⊗ Secrets in code\n\n## Code Search\n\n- ! use `rg`, or `ast-grep` (when available) instead of grep\n- ! Use Warp's built-in grep (which is rg) when running on warp\n- ~ Install if missing\n- ? Fall back to `grep` command only if tools cannot be installed\n\n## Version Control\n\nSee [../scm/git.md](../scm/git.md) for:\n- Commit conventions (Conventional Commits)\n- Safety rules (no force-push without permission)\n- Branch workflows\n\n## Code Design\n\n**Modularity:**\n- ! One responsibility per file/module\n- ~ Files <300 lines ideal; <500 lines recommended; <1000 lines a review trigger — split when exceeded unless genuinely single-responsibility (size is a smell, not a hard cap; #1488)\n- ! Explicit scope in task descriptions\n- ~ DRY: extract shared abstractions when logic is duplicated across 2+ call sites\n- ⊗ Copy-paste logic with minor variations — parameterise instead\n\n**Dependency Direction:**\n- ⊗ Circular imports between modules/packages\n- ~ Layered architecture: high-level modules depend on low-level ones, never the reverse\n- ! Use dependency inversion (interfaces/protocols) to break coupling across layers\n- See [hygiene.md](hygiene.md) for detection tools (madge, pydeps, Go compiler)\n\n**Contract-First:**\n- ! Define interfaces/types/protocols before implementation\n- ! Changes to public interfaces require explicit versioning or deprecation path\n- ! Document all public API contracts clearly\n\n**Immutability:**\n- ~ Prefer immutable data + pure functions\n- ~ When mutation needed, use narrow owned scopes (context managers, RAII)\n- ⊗ Global or singleton mutable state (almost always)\n\n**Error Handling:**\n- ~ Prefer Result/Option types or explicit exceptions over None/null/undefined\n- ! Document possible exceptions/error codes for all public functions\n- ! Validate all inputs at API boundaries\n- ⊗ Trust caller without validation\n- ⊗ Empty catch/except/recover blocks that swallow errors silently\n- ⊗ Returning neutral/zero values (None, {}, [], 0, false, \"\") to mask errors — propagate explicitly\n- ⊗ Log-and-continue: catching an error and proceeding as if it didn't happen, unless provably non-fatal and documented\n- See [hygiene.md](hygiene.md) for full error-hiding anti-pattern catalogue\n\n**Readability:**\n- ! Follow language idioms strictly\n- ! Meaningful names over short names\n- ! Comments explain **why**, code shows **what**\n- ⊗ Clever code over clear code\n\n**State & Data Modeling (#1695):**\n- ! A field MUST encode exactly one fact. Do NOT overload a field's value — or its presence/absence — to also signal a second orthogonal concern. Smuggling decision-, config-, lifecycle-, or control-state through a data field is *in-band signaling*; give that signal its own out-of-band field.\n- ! \"Absence is not a decision.\" Distinguish \"unset / never considered\" from \"deliberately set to the default.\" If a workflow must know a human made a choice, record the choice explicitly — never infer it from whether a value-field is present.\n- ~ Orthogonality test: if two facts can vary independently (e.g. value==default while decided ∈ {true,false}), they MUST live in separate slots. If one fact strictly implies the other (true Optional<T>, tombstones), sharing a slot is fine.\n- ⊗ Infer decision / onboarding / configuration state from the presence of a value field. Use an explicit out-of-band marker — cf. the resolver `source` provenance pattern (typed | default | default-on-error) directive already uses for *value*-provenance.\n- See [../patterns/in-band-signaling.md](../patterns/in-band-signaling.md) for the full model, orthogonality procedure, and the wipCap worked example (#1694).\n\n## Quality Standards\n\n**General:**\n- ! Run all relevant checks (lint, fmt, quality, build, test) before submitting changes\n- ⊗ Claim checks passed without running them\n- ! If checks cannot run, explicitly state why and what would have been executed\n- ~ Prioritize code quality and readability over backwards compatibility\n\n**Testing:**\n- ! Implementation is INCOMPLETE until tests written AND `task test:coverage` passes\n- See [../coding/testing.md](../coding/testing.md) for universal requirements\n\n**Security:**\n- ! Apply baseline security standards to every project from day one\n- See [../coding/security.md](../coding/security.md) for input validation, authn/authz, secrets, dependency, TOCTOU / mutable-external-resource rules (#1938), and agent-specific threats (#661)\n\n**Codebase Hygiene:**\n- See [hygiene.md](hygiene.md) for: dead code removal, circular dependency detection, error hiding patterns, legacy/deprecated code cleanup\n\n**Telemetry:**\n- See [../tools/telemetry.md](../tools/telemetry.md) for recommendations\n- ~ Structured logging for production\n- ~ Error tracking (Sentry.io or equivalent)\n- ? Distributed tracing for complex systems\n\n## Fail Loud: Completion Claims Require Outcome Verification (#1006)\n\nThe failure mode is the agent stating completion at the level of **intent** (\"I ran the migration\", \"the tests pass\", \"the feature works\") rather than at the level of **outcome verification** (\"all 167 records migrated, 0 skipped\", \"42 tests collected, 42 passed, 0 skipped, 0 xfailed\", \"the edge case asked about was reproduced and now returns the expected value\"). Outcome-blind completion claims hide silent skips, swallowed exceptions, suppressed errors, and unverified edge cases behind successful-sounding language. The example from the source: a database migration that completed \"successfully\" had silently skipped 14% of records on a constraint violation; the skip was logged but not surfaced; the bad reports were discovered 11 days later.\n\nThis rule is the OPERATIONAL complement to the EPISTEMIC honesty rules elsewhere in the framework (`main.md` morals section: don't present speculation as fact; label unverified claims). Morals.md says \"don't lie\". Fail-loud says \"count the records, check the logs, run the edge case, **then** claim completion.\" It is also the output-side complement to goal-gate-determinism (the gate specifies what evidence is required) and machine-verifiable-spec (verification commands prevent silent skips) -- without fail-loud, an agent can satisfy the letter of a gate (\"tests pass\") while hiding the gap (\"some tests were skipped\").\n\n- ! Before claiming a batch operation succeeded, MUST verify the record count and surface it in the claim (\"migrated 167/167 records, 0 skipped, 0 errored\" -- not \"migration completed\")\n- ! Before claiming \"tests pass\", MUST report the count of collected / passed / skipped / xfailed / errored tests (\"42 collected, 42 passed, 0 skipped\" -- not \"tests pass\"). A skipped or xfailed test is NOT a passing test for the purpose of this claim\n- ! Before claiming \"the feature works\", MUST report the specific edge case that was verified (if the user asked about a specific edge case, that edge case MUST be in the verification report; \"the happy path works\" is not equivalent to \"the feature works\")\n- ! Before claiming a migration / data transform / batch job completed, MUST check the error log AND the skip log AND the constraint-violation surface; surface the counts even when zero (\"0 skipped, 0 errored\" is the load-bearing claim, not silence)\n- ! When uncertainty exists about whether something worked, MUST surface the uncertainty explicitly (\"the migration completed and reported success but I have not verified the per-record count -- recommend running `<verification-command>` before declaring done\")\n- ⊗ MUST NOT claim \"tests pass\" when any test was skipped, xfailed, or run with errors suppressed -- report the full counts instead\n- ⊗ MUST NOT claim \"migration completed\" / \"batch succeeded\" / \"job finished\" without checking and reporting the per-record outcome counts\n- ⊗ MUST NOT claim \"feature works\" when only the happy path was verified -- name the edge case that was tested, or surface that it wasn't\n- ⊗ MUST NOT use successful-sounding completion phrasing to paper over uncertainty -- default to surfacing uncertainty, not hiding it\n- ⊗ MUST NOT suppress error output (`2>$null`, `2>/dev/null`, `try/except: pass` around the verification command) and then claim completion based on the resulting silence\n\n- ! Before claiming \"feature complete\", \"ready for real users\", \"production-ready\", or equivalent area-complete language for a surface that has open graduations (Now+Later dual-path locks; #2899), MUST name the open `graduationRef`s, **or** explicitly state that graduation review was skipped and why — otherwise the claim is outcome-blind under this rule\n- ⊗ MUST NOT claim \"feature complete\" / \"production-ready\" / \"ready for real users\" for an area with open graduations without naming those `graduationRef`s or an explicit skip-with-reason\n\nThe rule applies to agent completion claims during task execution. It applies equally to claims to the user, claims in commit messages, claims in PR bodies, claims in CHANGELOG entries, and claims in status messages to a parent agent. A short, honest \"the migration completed; I did not verify the per-record count\" is strictly preferred over a confident \"migration completed successfully\" that hides the gap.\n\n**Cross-references:** strategies discuss/probe Graduation dual-path locks (#2899); `## Quality Standards` above (`⊗ Claim checks passed without running them` -- the sibling rule that this expands from process to outcome); `hygiene.md` `## Error Handling: No Hiding` (the same hiding pattern at the code-write level, not the claim level); `skills/deft-directive-pre-pr/SKILL.md` (pre-PR verification claims); `skills/deft-directive-build/SKILL.md` Step 4 Quality Gates (task-completion claims); `skills/deft-directive-review-cycle/SKILL.md` (the review-cycle skill explicitly checks for hidden incompleteness in fix-batch completion claims).\n\n## Calling LLM APIs (#481)\n\nWhen the project calls LLM APIs (OpenAI, Anthropic, Cohere, local models, etc.) or builds agentic functionality, the architectural standards in `patterns/llm-app.md` apply alongside the coding rules above. In the directive maintainer repo this section is **guidance for consumer projects** — provider names are illustrative labels under the framework instruction hierarchy, not runtime SDK surfaces (#2414; see `meta/security.md` `## Informational AppSec findings`). The short form:\n\n- ! User input is NEVER placed in the system prompt; the system prompt is the trust boundary\n- ! External content is ALWAYS wrapped in explicit delimiters (`<user_input>`, `<document>`, `<tool_result>`) and surfaces its trust tier\n- ! Tool call arguments are validated against a schema BEFORE execution (the LLM is a confused deputy)\n- ! LLM outputs are validated against expected schemas before being acted upon (no eval-of-output, no shell-of-output, no SQL-of-output)\n- ⊗ MUST NOT write LLM outputs back into the retrieval corpus in the same session without validation (RAG poisoning vector)\n\nSee [../patterns/llm-app.md](../patterns/llm-app.md) for the full standards: prompt construction, trust tiers, tool/function-call validation, RAG hygiene, output handling, multi-agent orchestration, and LLM-specific observability. See [../tools/telemetry.md](../tools/telemetry.md) `## LLM-specific observability (#481)` for the matching observability surface.\n\n## Debugging and Root-Cause Investigation (#1621)\n\nWhen a bug, failure, or unexpected behaviour needs diagnosis, the root-cause standards in `debugging.md` apply. The short form:\n\n- ! No fixes without root-cause investigation first (the Iron Law)\n- ! Reproduce the failure consistently before proposing a fix — a non-reproducible bug is not yet understood\n- ! Every factual claim cites evidence; an uncited claim is a `[HYPOTHESIS]`, not a finding (evidence before narrative)\n- ! Runtime/config values are proven from the runtime, never inferred from source code (config is not code)\n- ⊗ MUST NOT present a duration or an exit status (\"slow because phase X took N minutes\", \"failed because it timed out\") as a root cause — name a mechanism (no tautologies)\n- ! After 3 failed distinct fixes, STOP and escalate for architectural review (the 3-fix gate)\n\nSee [debugging.md](debugging.md) for the full four-phase process, evidence discipline, Fact vs Hypothesis labeling (#1580), the observability-gap loop, and the rationalization table. For a sustained multi-agent investigation posture, see the `deft-directive-debug` skill.\n\n## Build Automation\n\n**Taskfile:**\n- ! Use Task ([go-task](https://taskfile.dev)) for all repeatable operations\n- ! If `task` not found, attempt to install go-task\n- ! If installation fails, stop and ask user for help\n- See [../tools/taskfile.md](../tools/taskfile.md) for standards and common commands\n\n**Toolchain Validation:**\n- See [../coding/toolchain.md](../coding/toolchain.md) for rules on verifying required tools are installed before implementation begins\n\n**Build Output Validation:**\n- See [../coding/build-output.md](../coding/build-output.md) for rules on verifying `dist/` artifacts and non-compiled assets after custom build scripts run\n\n## Change Management\n\n**Impact Awareness:**\n- ! Before changing shared code, identify affected downstream modules/files\n- ~ Prefer additive changes (new functions, fields with defaults) over breaking renames\n- ! Make small, reversible changes\n- ! Explain impact and migration path for breaking changes\n\n**Production Safety:**\n- ! Assume production impact unless stated otherwise\n- ! Call out risk when touching: auth, billing, data, APIs, build systems\n- ⊗ Silent breaking behavior\n- ~ Test changes in staging/dev environment when possible\n\n## Language-Specific Guidelines\n\n**Languages:**\n- C++: [../languages/cpp.md](../languages/cpp.md)\n- Go: [../languages/go.md](../languages/go.md)\n- Office.js: [../languages/officejs.md](../languages/officejs.md)\n- Python: [../languages/python.md](../languages/python.md)\n- TypeScript: [../languages/typescript.md](../languages/typescript.md)\n- VBA: [../languages/vba.md](../languages/vba.md)\n\n**Interface Types:**\n- CLI: [../interfaces/cli.md](../interfaces/cli.md)\n- TUI: [../interfaces/tui.md](../interfaces/tui.md)\n- Web: [../interfaces/web.md](../interfaces/web.md)\n- REST API: [../interfaces/rest.md](../interfaces/rest.md)\n\n## Development Workflow\n\n**Localhost:**\n- No permission needed for curl localhost\n\n**Plans:**\n- ~ Create both:\n 1. Warp plan (using `create_plan` tool)\n 2. Archive copy in `history/plan-YYYY-MM-DD-description.md`\n\n## Project Context\n\n- ! Check [PROJECT.md](../../PROJECT.md) for project-specific overrides\n- ~ Inspect project config (package.json, pyproject.toml, etc.) for available scripts\n- ! Follow project-specific testing, coverage, and quality requirements\n\n## Anti-Patterns\n\n- ⊗ Secrets in code or version control\n- ⊗ Claiming checks passed without running them\n- ⊗ Single files mixing multiple responsibilities (large line count, e.g. >1000 lines, is a trigger to check cohesion — not a defect by itself; #1488)\n- ⊗ Skipping quality checks\n- ⊗ Breaking changes without explicit approval\n- ⊗ Using `grep` command when `rg` or Warp grep available\n- ⊗ Implementing code without tests\n- ⊗ Claiming \"done\" before running test:coverage\n- ⊗ Ignoring coverage drops\n- ⊗ Weak types (`any`, `interface{}`, untyped `object`) where concrete types are knowable\n- ⊗ Dead code: unused functions, unreachable branches, stale feature flags, commented-out blocks\n- ⊗ Error hiding: empty catch blocks, silent fallbacks, swallowed exceptions\n- ⊗ Circular imports between modules\n- ⊗ Duplicate logic across 2+ call sites without shared abstraction\n- ⊗ Outcome-blind completion claims: \"tests pass\" with skipped tests, \"migration completed\" without per-record counts, \"feature works\" without naming the verified edge case (#1006 -- see `## Fail Loud` above)\n- ⊗ Outcome-blind \"feature complete\" / \"production-ready\" claims that ignore open graduations (`graduationRef`s) without naming them or an explicit skip (#2899 / #1006 -- see `## Fail Loud` above)\n- ⊗ Averaging contradicting codebase patterns: writing new code that satisfies both of two conflicting patterns simultaneously (#1005 -- see `hygiene.md` `## Surface Conflicts`)\n- ⊗ Debugging by guess-and-check: fixing before reproducing, treating the first plausible hypothesis as confirmed, or presenting a duration/exit-status as a root cause (#1621 -- see `debugging.md`)\n"
68
+ "body": "\n# Coding Guidelines\n\nSoftware development specific guidelines for AI agents.\n\nLegend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY.\n\n**⚠️ See also** (load only when needed):\n- [../main.md](../../main.md) - General AI behavior and agent persona\n- [PROJECT.md](../../PROJECT.md) - For project-specific overrides\n- [../tools/telemetry.md](../tools/telemetry.md) - When implementing logging/tracing/metrics\n\n## Code Organization\n\n**Documentation:**\n- ! All *.md in `docs/` directory (except README.md, AGENTS.md, WARP.md)\n- ! Prior tasks/plans in `history/`\n- ! When code changes user-visible behavior, update matching user-facing docs in the same PR — see [docs.md](docs.md) (#447; lazy-load, not AGENTS always-on)\n\n**Filenames:**\n- ~ Use hyphens not underscores (unless language idiom)\n\n**Secrets:**\n- ! ALL secrets in `secrets/` dir as .env files\n- ⊗ Secrets in code\n\n## Code Search\n\n- ! use `rg`, or `ast-grep` (when available) instead of grep\n- ! Use Warp's built-in grep (which is rg) when running on warp\n- ~ Install if missing\n- ? Fall back to `grep` command only if tools cannot be installed\n\n## Version Control\n\nSee [../scm/git.md](../scm/git.md) for:\n- Commit conventions (Conventional Commits)\n- Safety rules (no force-push without permission)\n- Branch workflows\n\n## Code Design\n\n**Modularity:**\n- ! One responsibility per file/module\n- ~ Files <300 lines ideal; <500 lines recommended; <1000 lines a review trigger — split when exceeded unless genuinely single-responsibility (size is a smell, not a hard cap; #1488)\n- ! Explicit scope in task descriptions\n- ~ DRY: extract shared abstractions when logic is duplicated across 2+ call sites\n- ⊗ Copy-paste logic with minor variations — parameterise instead\n\n**Dependency Direction:**\n- ⊗ Circular imports between modules/packages\n- ~ Layered architecture: high-level modules depend on low-level ones, never the reverse\n- ! Use dependency inversion (interfaces/protocols) to break coupling across layers\n- See [hygiene.md](hygiene.md) for detection tools (madge, pydeps, Go compiler)\n\n**Contract-First:**\n- ! Define interfaces/types/protocols before implementation\n- ! Changes to public interfaces require explicit versioning or deprecation path\n- ! Document all public API contracts clearly\n\n**Immutability:**\n- ~ Prefer immutable data + pure functions\n- ~ When mutation needed, use narrow owned scopes (context managers, RAII)\n- ⊗ Global or singleton mutable state (almost always)\n\n**Error Handling:**\n- ~ Prefer Result/Option types or explicit exceptions over None/null/undefined\n- ! Document possible exceptions/error codes for all public functions\n- ! Validate all inputs at API boundaries\n- ⊗ Trust caller without validation\n- ⊗ Empty catch/except/recover blocks that swallow errors silently\n- ⊗ Returning neutral/zero values (None, {}, [], 0, false, \"\") to mask errors — propagate explicitly\n- ⊗ Log-and-continue: catching an error and proceeding as if it didn't happen, unless provably non-fatal and documented\n- See [hygiene.md](hygiene.md) for full error-hiding anti-pattern catalogue\n\n**Readability:**\n- ! Follow language idioms strictly\n- ! Meaningful names over short names\n- ! Comments explain **why**, code shows **what**\n- ⊗ Clever code over clear code\n\n**State & Data Modeling (#1695):**\n- ! A field MUST encode exactly one fact. Do NOT overload a field's value — or its presence/absence — to also signal a second orthogonal concern. Smuggling decision-, config-, lifecycle-, or control-state through a data field is *in-band signaling*; give that signal its own out-of-band field.\n- ! \"Absence is not a decision.\" Distinguish \"unset / never considered\" from \"deliberately set to the default.\" If a workflow must know a human made a choice, record the choice explicitly — never infer it from whether a value-field is present.\n- ~ Orthogonality test: if two facts can vary independently (e.g. value==default while decided ∈ {true,false}), they MUST live in separate slots. If one fact strictly implies the other (true Optional<T>, tombstones), sharing a slot is fine.\n- ⊗ Infer decision / onboarding / configuration state from the presence of a value field. Use an explicit out-of-band marker — cf. the resolver `source` provenance pattern (typed | default | default-on-error) directive already uses for *value*-provenance.\n- See [../patterns/in-band-signaling.md](../patterns/in-band-signaling.md) for the full model, orthogonality procedure, and the wipCap worked example (#1694).\n\n## Quality Standards\n\n**General:**\n- ! Run all relevant checks (lint, fmt, quality, build, test) before submitting changes\n- ⊗ Claim checks passed without running them\n- ! If checks cannot run, explicitly state why and what would have been executed\n- ~ Prioritize code quality and readability over backwards compatibility\n\n**Testing:**\n- ! Implementation is INCOMPLETE until tests written AND `task test:coverage` passes\n- See [../coding/testing.md](../coding/testing.md) for universal requirements\n\n**Security:**\n- ! Apply baseline security standards to every project from day one\n- See [../coding/security.md](../coding/security.md) for input validation, authn/authz, secrets, dependency, TOCTOU / mutable-external-resource rules (#1938), and agent-specific threats (#661)\n\n**Review process (#1471 / #212):**\n- ! Apply tool-agnostic review-cycle principles on every PR review response\n- See [review.md](review.md) for read-all-findings, severity P0/P1/P2, single batch commit, cross-file grep, no mid-review push, exit on no P0/P1, and post-merge closing-keyword verification\n- Greptile/GitHub adapter: [../skills/deft-directive-review-cycle/SKILL.md](../skills/deft-directive-review-cycle/SKILL.md)\n\n**Codebase Hygiene:**\n- See [hygiene.md](hygiene.md) for: dead code removal, circular dependency detection, error hiding patterns, legacy/deprecated code cleanup\n\n**Telemetry:**\n- See [../tools/telemetry.md](../tools/telemetry.md) for recommendations\n- ~ Structured logging for production\n- ~ Error tracking (Sentry.io or equivalent)\n- ? Distributed tracing for complex systems\n\n## Fail Loud: Completion Claims Require Outcome Verification (#1006)\n\nThe failure mode is the agent stating completion at the level of **intent** (\"I ran the migration\", \"the tests pass\", \"the feature works\") rather than at the level of **outcome verification** (\"all 167 records migrated, 0 skipped\", \"42 tests collected, 42 passed, 0 skipped, 0 xfailed\", \"the edge case asked about was reproduced and now returns the expected value\"). Outcome-blind completion claims hide silent skips, swallowed exceptions, suppressed errors, and unverified edge cases behind successful-sounding language. The example from the source: a database migration that completed \"successfully\" had silently skipped 14% of records on a constraint violation; the skip was logged but not surfaced; the bad reports were discovered 11 days later.\n\nThis rule is the OPERATIONAL complement to the EPISTEMIC honesty rules elsewhere in the framework (`main.md` morals section: don't present speculation as fact; label unverified claims). Morals.md says \"don't lie\". Fail-loud says \"count the records, check the logs, run the edge case, **then** claim completion.\" It is also the output-side complement to goal-gate-determinism (the gate specifies what evidence is required) and machine-verifiable-spec (verification commands prevent silent skips) -- without fail-loud, an agent can satisfy the letter of a gate (\"tests pass\") while hiding the gap (\"some tests were skipped\").\n\n- ! Before claiming a batch operation succeeded, MUST verify the record count and surface it in the claim (\"migrated 167/167 records, 0 skipped, 0 errored\" -- not \"migration completed\")\n- ! Before claiming \"tests pass\", MUST report the count of collected / passed / skipped / xfailed / errored tests (\"42 collected, 42 passed, 0 skipped\" -- not \"tests pass\"). A skipped or xfailed test is NOT a passing test for the purpose of this claim\n- ! Before claiming \"the feature works\", MUST report the specific edge case that was verified (if the user asked about a specific edge case, that edge case MUST be in the verification report; \"the happy path works\" is not equivalent to \"the feature works\")\n- ! Before claiming a migration / data transform / batch job completed, MUST check the error log AND the skip log AND the constraint-violation surface; surface the counts even when zero (\"0 skipped, 0 errored\" is the load-bearing claim, not silence)\n- ! When uncertainty exists about whether something worked, MUST surface the uncertainty explicitly (\"the migration completed and reported success but I have not verified the per-record count -- recommend running `<verification-command>` before declaring done\")\n- ⊗ MUST NOT claim \"tests pass\" when any test was skipped, xfailed, or run with errors suppressed -- report the full counts instead\n- ⊗ MUST NOT claim \"migration completed\" / \"batch succeeded\" / \"job finished\" without checking and reporting the per-record outcome counts\n- ⊗ MUST NOT claim \"feature works\" when only the happy path was verified -- name the edge case that was tested, or surface that it wasn't\n- ⊗ MUST NOT use successful-sounding completion phrasing to paper over uncertainty -- default to surfacing uncertainty, not hiding it\n- ⊗ MUST NOT suppress error output (`2>$null`, `2>/dev/null`, `try/except: pass` around the verification command) and then claim completion based on the resulting silence\n\n- ! Before claiming \"feature complete\", \"ready for real users\", \"production-ready\", or equivalent area-complete language for a surface that has open graduations (Now+Later dual-path locks; #2899), MUST name the open `graduationRef`s, **or** explicitly state that graduation review was skipped and why — otherwise the claim is outcome-blind under this rule\n- ⊗ MUST NOT claim \"feature complete\" / \"production-ready\" / \"ready for real users\" for an area with open graduations without naming those `graduationRef`s or an explicit skip-with-reason\n\nThe rule applies to agent completion claims during task execution. It applies equally to claims to the user, claims in commit messages, claims in PR bodies, claims in CHANGELOG entries, and claims in status messages to a parent agent. A short, honest \"the migration completed; I did not verify the per-record count\" is strictly preferred over a confident \"migration completed successfully\" that hides the gap.\n\n**Cross-references:** strategies discuss/probe Graduation dual-path locks (#2899); `## Quality Standards` above (`⊗ Claim checks passed without running them` -- the sibling rule that this expands from process to outcome); `hygiene.md` `## Error Handling: No Hiding` (the same hiding pattern at the code-write level, not the claim level); `skills/deft-directive-pre-pr/SKILL.md` (pre-PR verification claims); `skills/deft-directive-build/SKILL.md` Step 4 Quality Gates (task-completion claims); `skills/deft-directive-review-cycle/SKILL.md` (Greptile adapter; universal review principles in [review.md](review.md); the adapter explicitly checks for hidden incompleteness in fix-batch completion claims).\n\n## Calling LLM APIs (#481)\n\nWhen the project calls LLM APIs (OpenAI, Anthropic, Cohere, local models, etc.) or builds agentic functionality, the architectural standards in `patterns/llm-app.md` apply alongside the coding rules above. In the directive maintainer repo this section is **guidance for consumer projects** — provider names are illustrative labels under the framework instruction hierarchy, not runtime SDK surfaces (#2414; see `meta/security.md` `## Informational AppSec findings`). The short form:\n\n- ! User input is NEVER placed in the system prompt; the system prompt is the trust boundary\n- ! External content is ALWAYS wrapped in explicit delimiters (`<user_input>`, `<document>`, `<tool_result>`) and surfaces its trust tier\n- ! Tool call arguments are validated against a schema BEFORE execution (the LLM is a confused deputy)\n- ! LLM outputs are validated against expected schemas before being acted upon (no eval-of-output, no shell-of-output, no SQL-of-output)\n- ⊗ MUST NOT write LLM outputs back into the retrieval corpus in the same session without validation (RAG poisoning vector)\n\nSee [../patterns/llm-app.md](../patterns/llm-app.md) for the full standards: prompt construction, trust tiers, tool/function-call validation, RAG hygiene, output handling, multi-agent orchestration, and LLM-specific observability. See [../tools/telemetry.md](../tools/telemetry.md) `## LLM-specific observability (#481)` for the matching observability surface.\n\n## Debugging and Root-Cause Investigation (#1621)\n\nWhen a bug, failure, or unexpected behaviour needs diagnosis, the root-cause standards in `debugging.md` apply. The short form:\n\n- ! No fixes without root-cause investigation first (the Iron Law)\n- ! Reproduce the failure consistently before proposing a fix — a non-reproducible bug is not yet understood\n- ! Every factual claim cites evidence; an uncited claim is a `[HYPOTHESIS]`, not a finding (evidence before narrative)\n- ! Runtime/config values are proven from the runtime, never inferred from source code (config is not code)\n- ⊗ MUST NOT present a duration or an exit status (\"slow because phase X took N minutes\", \"failed because it timed out\") as a root cause — name a mechanism (no tautologies)\n- ! After 3 failed distinct fixes, STOP and escalate for architectural review (the 3-fix gate)\n\nSee [debugging.md](debugging.md) for the full four-phase process, evidence discipline, Fact vs Hypothesis labeling (#1580), the observability-gap loop, and the rationalization table. For a sustained multi-agent investigation posture, see the `deft-directive-debug` skill.\n\n## Build Automation\n\n**Taskfile:**\n- ! Use Task ([go-task](https://taskfile.dev)) for all repeatable operations\n- ! If `task` not found, attempt to install go-task\n- ! If installation fails, stop and ask user for help\n- See [../tools/taskfile.md](../tools/taskfile.md) for standards and common commands\n\n**Toolchain Validation:**\n- See [../coding/toolchain.md](../coding/toolchain.md) for rules on verifying required tools are installed before implementation begins\n\n**Build Output Validation:**\n- See [../coding/build-output.md](../coding/build-output.md) for rules on verifying `dist/` artifacts and non-compiled assets after custom build scripts run\n\n## Change Management\n\n**Impact Awareness:**\n- ! Before changing shared code, identify affected downstream modules/files\n- ~ Prefer additive changes (new functions, fields with defaults) over breaking renames\n- ! Make small, reversible changes\n- ! Explain impact and migration path for breaking changes\n\n**Production Safety:**\n- ! Assume production impact unless stated otherwise\n- ! Call out risk when touching: auth, billing, data, APIs, build systems\n- ⊗ Silent breaking behavior\n- ~ Test changes in staging/dev environment when possible\n\n## Language-Specific Guidelines\n\n**Languages:**\n- C++: [../languages/cpp.md](../languages/cpp.md)\n- Go: [../languages/go.md](../languages/go.md)\n- Office.js: [../languages/officejs.md](../languages/officejs.md)\n- Python: [../languages/python.md](../languages/python.md)\n- TypeScript: [../languages/typescript.md](../languages/typescript.md)\n- VBA: [../languages/vba.md](../languages/vba.md)\n\n**Interface Types:**\n- CLI: [../interfaces/cli.md](../interfaces/cli.md)\n- TUI: [../interfaces/tui.md](../interfaces/tui.md)\n- Web: [../interfaces/web.md](../interfaces/web.md)\n- REST API: [../interfaces/rest.md](../interfaces/rest.md)\n\n## Development Workflow\n\n**Localhost:**\n- No permission needed for curl localhost\n\n**Plans:**\n- ~ Create both:\n 1. Warp plan (using `create_plan` tool)\n 2. Archive copy in `history/plan-YYYY-MM-DD-description.md`\n\n## Project Context\n\n- ! Check [PROJECT.md](../../PROJECT.md) for project-specific overrides\n- ~ Inspect project config (package.json, pyproject.toml, etc.) for available scripts\n- ! Follow project-specific testing, coverage, and quality requirements\n\n## Anti-Patterns\n\n- ⊗ Secrets in code or version control\n- ⊗ Claiming checks passed without running them\n- ⊗ Single files mixing multiple responsibilities (large line count, e.g. >1000 lines, is a trigger to check cohesion — not a defect by itself; #1488)\n- ⊗ Skipping quality checks\n- ⊗ Breaking changes without explicit approval\n- ⊗ Using `grep` command when `rg` or Warp grep available\n- ⊗ Implementing code without tests\n- ⊗ Claiming \"done\" before running test:coverage\n- ⊗ Ignoring coverage drops\n- ⊗ Weak types (`any`, `interface{}`, untyped `object`) where concrete types are knowable\n- ⊗ Dead code: unused functions, unreachable branches, stale feature flags, commented-out blocks\n- ⊗ Error hiding: empty catch blocks, silent fallbacks, swallowed exceptions\n- ⊗ Circular imports between modules\n- ⊗ Duplicate logic across 2+ call sites without shared abstraction\n- ⊗ Outcome-blind completion claims: \"tests pass\" with skipped tests, \"migration completed\" without per-record counts, \"feature works\" without naming the verified edge case (#1006 -- see `## Fail Loud` above)\n- ⊗ Outcome-blind \"feature complete\" / \"production-ready\" claims that ignore open graduations (`graduationRef`s) without naming them or an explicit skip (#2899 / #1006 -- see `## Fail Loud` above)\n- ⊗ Averaging contradicting codebase patterns: writing new code that satisfies both of two conflicting patterns simultaneously (#1005 -- see `hygiene.md` `## Surface Conflicts`)\n- ⊗ Debugging by guess-and-check: fixing before reproducing, treating the first plausible hypothesis as confirmed, or presenting a duration/exit-status as a root cause (#1621 -- see `debugging.md`)\n"
69
69
  },
70
70
  {
71
71
  "id": "coding-002",
@@ -1939,6 +1939,134 @@
1939
1939
  "path": "coding/hygiene.md",
1940
1940
  "body": null
1941
1941
  },
1942
+ {
1943
+ "id": "review-001",
1944
+ "tier": "MUST",
1945
+ "domain": "review",
1946
+ "text": "ALL review findings MUST be read before any fixes begin",
1947
+ "path": "coding/review.md",
1948
+ "body": "# Review Cycle Principles\n\nTool-agnostic principles for responding to code review findings on a PR. Adapters\n(Greptile, CodeRabbit, Codacy, host babysit loops, …) implement these with\ntool-specific mechanics. This file is the single source of truth for the\nuniversal process so consumers without a given adapter skill still get the\nreview discipline (#1471 / #212).\n\nLegend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY.\n\n**See also:** [coding.md](coding.md) (quality chain) · [testing.md](testing.md) ·\n[skills/deft-directive-review-cycle/SKILL.md](../skills/deft-directive-review-cycle/SKILL.md)\n(Greptile + GitHub adapter)\n\n## Universal Requirements\n\n- ! ALL review findings MUST be read before any fixes begin\n- ! Findings MUST be classified by severity: **P0** (critical/blocking), **P1** (real defect), **P2** (style / non-blocking). P0 and P1 are merge-blocking; P2 is not\n- ! Findings MUST be fixed in a single batch commit — never incrementally per finding\n- ! Changed values, terms, or fields MUST be grepped across all PR files for cross-file consistency in the same batch\n- ~ Structured data files (JSON / YAML / TOML) SHOULD be validated locally before commit (e.g. `python3 -m json.tool`, YAML lint) — do not rely on the reviewer alone to catch syntax errors\n- ! Do not push additional commits while a review is in progress on the current head\n- ! Exit condition: no P0 or P1 remaining = ready to merge; P2 does not block merge\n- ! Post-merge: verify that closing keywords (`Closes #N`, `Fixes #N`) actually closed the referenced issues (squash-merge pitfall; #167)\n\n## Severity and merge gate\n\n| Severity | Meaning | Blocks merge? |\n| --- | --- | --- |\n| P0 | Critical / correctness / security / data-loss | Yes |\n| P1 | Real defect or incomplete acceptance | Yes |\n| P2 | Style, nits, non-blocking suggestion | No |\n\n- ! Agents MUST NOT claim merge-ready while any P0 or P1 from the current review remains open\n- ⊗ Elevate P2-only findings into a merge block without operator agreement\n\n## Anti-Patterns\n\n- ⊗ Start fixing individual findings as you encounter them — read and plan the full batch first\n- ⊗ Push one commit per finding\n- ⊗ Push while a bot or human review of the current head is still in flight\n- ⊗ Treat P2-only findings as merge-blocking by default\n- ⊗ Assume squash merge auto-closed referenced issues — always verify issue state after merge (#167)\n- ⊗ Skip cross-file grep when a fix renames or retargets a shared term/value/field\n"
1949
+ },
1950
+ {
1951
+ "id": "review-002",
1952
+ "tier": "MUST",
1953
+ "domain": "review",
1954
+ "text": "Findings MUST be classified by severity: P0 (critical/blocking), P1 (real defect), P2 (style / non-blocking). P0 and P1 are merge-blocking; P2 is not",
1955
+ "path": "coding/review.md",
1956
+ "body": null
1957
+ },
1958
+ {
1959
+ "id": "review-003",
1960
+ "tier": "MUST",
1961
+ "domain": "review",
1962
+ "text": "Findings MUST be fixed in a single batch commit — never incrementally per finding",
1963
+ "path": "coding/review.md",
1964
+ "body": null
1965
+ },
1966
+ {
1967
+ "id": "review-004",
1968
+ "tier": "MUST",
1969
+ "domain": "review",
1970
+ "text": "Changed values, terms, or fields MUST be grepped across all PR files for cross-file consistency in the same batch",
1971
+ "path": "coding/review.md",
1972
+ "body": null
1973
+ },
1974
+ {
1975
+ "id": "review-005",
1976
+ "tier": "SHOULD",
1977
+ "domain": "review",
1978
+ "text": "Structured data files (JSON / YAML / TOML) SHOULD be validated locally before commit",
1979
+ "path": "coding/review.md",
1980
+ "body": null
1981
+ },
1982
+ {
1983
+ "id": "review-006",
1984
+ "tier": "MUST",
1985
+ "domain": "review",
1986
+ "text": "Do not push additional commits while a review is in progress on the current head",
1987
+ "path": "coding/review.md",
1988
+ "body": null
1989
+ },
1990
+ {
1991
+ "id": "review-007",
1992
+ "tier": "MUST",
1993
+ "domain": "review",
1994
+ "text": "Exit condition: no P0 or P1 remaining = ready to merge; P2 does not block merge",
1995
+ "path": "coding/review.md",
1996
+ "body": null
1997
+ },
1998
+ {
1999
+ "id": "review-008",
2000
+ "tier": "MUST",
2001
+ "domain": "review",
2002
+ "text": "Post-merge: verify that closing keywords (Closes #N, Fixes #N) actually closed the referenced issues (squash-merge pitfall)",
2003
+ "path": "coding/review.md",
2004
+ "body": null
2005
+ },
2006
+ {
2007
+ "id": "review-009",
2008
+ "tier": "MUST",
2009
+ "domain": "review",
2010
+ "text": "Agents MUST NOT claim merge-ready while any P0 or P1 from the current review remains open",
2011
+ "path": "coding/review.md",
2012
+ "body": null
2013
+ },
2014
+ {
2015
+ "id": "review-010",
2016
+ "tier": "MUST_NOT",
2017
+ "domain": "review",
2018
+ "text": "Elevate P2-only findings into a merge block without operator agreement",
2019
+ "path": "coding/review.md",
2020
+ "body": null
2021
+ },
2022
+ {
2023
+ "id": "review-011",
2024
+ "tier": "MUST_NOT",
2025
+ "domain": "review",
2026
+ "text": "Start fixing individual findings as you encounter them — read and plan the full batch first",
2027
+ "path": "coding/review.md",
2028
+ "body": null
2029
+ },
2030
+ {
2031
+ "id": "review-012",
2032
+ "tier": "MUST_NOT",
2033
+ "domain": "review",
2034
+ "text": "Push one commit per finding",
2035
+ "path": "coding/review.md",
2036
+ "body": null
2037
+ },
2038
+ {
2039
+ "id": "review-013",
2040
+ "tier": "MUST_NOT",
2041
+ "domain": "review",
2042
+ "text": "Push while a bot or human review of the current head is still in flight",
2043
+ "path": "coding/review.md",
2044
+ "body": null
2045
+ },
2046
+ {
2047
+ "id": "review-014",
2048
+ "tier": "MUST_NOT",
2049
+ "domain": "review",
2050
+ "text": "Treat P2-only findings as merge-blocking by default",
2051
+ "path": "coding/review.md",
2052
+ "body": null
2053
+ },
2054
+ {
2055
+ "id": "review-015",
2056
+ "tier": "MUST_NOT",
2057
+ "domain": "review",
2058
+ "text": "Assume squash merge auto-closed referenced issues — always verify issue state after merge",
2059
+ "path": "coding/review.md",
2060
+ "body": null
2061
+ },
2062
+ {
2063
+ "id": "review-016",
2064
+ "tier": "MUST_NOT",
2065
+ "domain": "review",
2066
+ "text": "Skip cross-file grep when a fix renames or retargets a shared term/value/field",
2067
+ "path": "coding/review.md",
2068
+ "body": null
2069
+ },
1942
2070
  {
1943
2071
  "id": "security-001",
1944
2072
  "tier": "MUST",
@@ -4858,6 +4986,14 @@
4858
4986
  "text": "Presenting naked curl|sh / wget|sh / irm|iex as the primary blessed install path (#2969)",
4859
4987
  "path": "coding/security.md",
4860
4988
  "body": null
4989
+ },
4990
+ {
4991
+ "id": "coding-docs-001",
4992
+ "path": "coding/docs.md",
4993
+ "domain": "documentation",
4994
+ "tier": "MUST",
4995
+ "body": "# Documentation with Code Changes (#447)\n\nKeep user-facing documentation current when code changes. Full rules live here so they are **not** always-loaded into AGENTS.md (consumer token cost).\n\nLegend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY.\n\n**See also** (load only when needed):\n- [coding.md](coding.md) — general coding standards\n- [../skills/deft-directive-pre-pr/SKILL.md](../skills/deft-directive-pre-pr/SKILL.md) — pre-PR checklist (operational)\n- [../docs/good-agents-md.md](../docs/good-agents-md.md) — AGENTS.md structure\n\n## When docs are required\n\n- ! If the change alters **user-visible behavior**, update the matching user-facing surface in the **same PR** (or same commit batch before PR)\n- ! User-facing surfaces include, as applicable:\n - CHANGELOG.md under `[Unreleased]` (when the change is user- or operator-visible)\n - CLI help / `commands.md` (or equivalent) when adding or changing a user-invoked command or flag\n - Getting-started / README pointers when install or first-run behavior changes\n - Skill or strategy \"When to use\" / trigger text when workflow entry points change\n- ~ Prefer updating the **canonical source** (xBRIEF, content pack, policy) and re-rendering generated views — do not hand-edit generated markdown as the sole fix\n- ⊗ Claim \"docs updated\" or \"documented\" without the documentation files appearing in the diff\n\n## When docs are optional\n\n- ? Invent documentation for pure internal refactors with no user-visible behavior change\n- ~ Internal-only comments and maintainer notes MAY ship without user-facing doc updates\n- ⊗ Expand always-loaded AGENTS.md with long documentation-discipline essays — keep this file lazy-loaded\n\n## Honesty\n\n- ! Documentation claims obey fail-loud / outcome verification (coding.md § Fail Loud): no completion claims that hide missing doc surfaces\n- ~ If a required surface is skipped, say so explicitly and why (same standard as \"checks not run\")\n\n## Anti-Patterns\n\n- ⊗ Shipping a new public task/CLI verb with no help or commands entry\n- ⊗ Leaving CHANGELOG stale after a user-visible fix\n- ⊗ Orphan docs (new md not reachable from AGENTS/README/reference chain — see pre-pr #644 / #647)\n",
4996
+ "text": "When code changes user-visible behavior, update matching user-facing docs in the same PR (see coding/docs.md)"
4861
4997
  }
4862
4998
  ]
4863
4999
  }