@deftai/directive-content 0.90.0 → 0.91.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.
@@ -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": "# 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## 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\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"
69
69
  },
70
70
  {
71
71
  "id": "coding-002",
@@ -335,12 +335,44 @@
335
335
  "id": "coding-035",
336
336
  "tier": "MUST",
337
337
  "domain": "coding",
338
- "text": "Run all relevant checks (lint, fmt, quality, build, test) before submitting changes",
338
+ "text": "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.",
339
339
  "path": "coding/coding.md",
340
340
  "body": null
341
341
  },
342
342
  {
343
343
  "id": "coding-036",
344
+ "tier": "MUST",
345
+ "domain": "coding",
346
+ "text": "\"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.",
347
+ "path": "coding/coding.md",
348
+ "body": null
349
+ },
350
+ {
351
+ "id": "coding-037",
352
+ "tier": "SHOULD",
353
+ "domain": "coding",
354
+ "text": "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.",
355
+ "path": "coding/coding.md",
356
+ "body": null
357
+ },
358
+ {
359
+ "id": "coding-038",
360
+ "tier": "MUST_NOT",
361
+ "domain": "coding",
362
+ "text": "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.",
363
+ "path": "coding/coding.md",
364
+ "body": null
365
+ },
366
+ {
367
+ "id": "coding-039",
368
+ "tier": "MUST",
369
+ "domain": "coding",
370
+ "text": "Run all relevant checks (lint, fmt, quality, build, test) before submitting changes",
371
+ "path": "coding/coding.md",
372
+ "body": null
373
+ },
374
+ {
375
+ "id": "coding-040",
344
376
  "tier": "MUST_NOT",
345
377
  "domain": "coding",
346
378
  "text": "Claim checks passed without running them",
@@ -348,7 +380,7 @@
348
380
  "body": null
349
381
  },
350
382
  {
351
- "id": "coding-037",
383
+ "id": "coding-041",
352
384
  "tier": "MUST",
353
385
  "domain": "coding",
354
386
  "text": "If checks cannot run, explicitly state why and what would have been executed",
@@ -356,7 +388,7 @@
356
388
  "body": null
357
389
  },
358
390
  {
359
- "id": "coding-038",
391
+ "id": "coding-042",
360
392
  "tier": "SHOULD",
361
393
  "domain": "coding",
362
394
  "text": "Prioritize code quality and readability over backwards compatibility",
@@ -364,7 +396,7 @@
364
396
  "body": null
365
397
  },
366
398
  {
367
- "id": "coding-039",
399
+ "id": "coding-043",
368
400
  "tier": "MUST",
369
401
  "domain": "coding",
370
402
  "text": "Implementation is INCOMPLETE until tests written AND `task test:coverage` passes",
@@ -372,7 +404,7 @@
372
404
  "body": null
373
405
  },
374
406
  {
375
- "id": "coding-040",
407
+ "id": "coding-044",
376
408
  "tier": "MUST",
377
409
  "domain": "coding",
378
410
  "text": "Apply baseline security standards to every project from day one",
@@ -380,7 +412,7 @@
380
412
  "body": null
381
413
  },
382
414
  {
383
- "id": "coding-041",
415
+ "id": "coding-045",
384
416
  "tier": "SHOULD",
385
417
  "domain": "coding",
386
418
  "text": "Structured logging for production",
@@ -388,7 +420,7 @@
388
420
  "body": null
389
421
  },
390
422
  {
391
- "id": "coding-042",
423
+ "id": "coding-046",
392
424
  "tier": "SHOULD",
393
425
  "domain": "coding",
394
426
  "text": "Error tracking (Sentry.io or equivalent)",
@@ -396,7 +428,7 @@
396
428
  "body": null
397
429
  },
398
430
  {
399
- "id": "coding-043",
431
+ "id": "coding-047",
400
432
  "tier": "MAY",
401
433
  "domain": "coding",
402
434
  "text": "Distributed tracing for complex systems",
@@ -404,7 +436,7 @@
404
436
  "body": null
405
437
  },
406
438
  {
407
- "id": "coding-044",
439
+ "id": "coding-048",
408
440
  "tier": "MUST",
409
441
  "domain": "coding",
410
442
  "text": "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\")",
@@ -412,7 +444,7 @@
412
444
  "body": null
413
445
  },
414
446
  {
415
- "id": "coding-045",
447
+ "id": "coding-049",
416
448
  "tier": "MUST",
417
449
  "domain": "coding",
418
450
  "text": "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",
@@ -420,7 +452,7 @@
420
452
  "body": null
421
453
  },
422
454
  {
423
- "id": "coding-046",
455
+ "id": "coding-050",
424
456
  "tier": "MUST",
425
457
  "domain": "coding",
426
458
  "text": "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\")",
@@ -428,7 +460,7 @@
428
460
  "body": null
429
461
  },
430
462
  {
431
- "id": "coding-047",
463
+ "id": "coding-051",
432
464
  "tier": "MUST",
433
465
  "domain": "coding",
434
466
  "text": "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)",
@@ -436,7 +468,7 @@
436
468
  "body": null
437
469
  },
438
470
  {
439
- "id": "coding-048",
471
+ "id": "coding-052",
440
472
  "tier": "MUST",
441
473
  "domain": "coding",
442
474
  "text": "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\")",
@@ -444,7 +476,7 @@
444
476
  "body": null
445
477
  },
446
478
  {
447
- "id": "coding-049",
479
+ "id": "coding-053",
448
480
  "tier": "MUST_NOT",
449
481
  "domain": "coding",
450
482
  "text": "MUST NOT claim \"tests pass\" when any test was skipped, xfailed, or run with errors suppressed -- report the full counts instead",
@@ -452,7 +484,7 @@
452
484
  "body": null
453
485
  },
454
486
  {
455
- "id": "coding-050",
487
+ "id": "coding-054",
456
488
  "tier": "MUST_NOT",
457
489
  "domain": "coding",
458
490
  "text": "MUST NOT claim \"migration completed\" / \"batch succeeded\" / \"job finished\" without checking and reporting the per-record outcome counts",
@@ -460,7 +492,7 @@
460
492
  "body": null
461
493
  },
462
494
  {
463
- "id": "coding-051",
495
+ "id": "coding-055",
464
496
  "tier": "MUST_NOT",
465
497
  "domain": "coding",
466
498
  "text": "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",
@@ -468,7 +500,7 @@
468
500
  "body": null
469
501
  },
470
502
  {
471
- "id": "coding-052",
503
+ "id": "coding-056",
472
504
  "tier": "MUST_NOT",
473
505
  "domain": "coding",
474
506
  "text": "MUST NOT use successful-sounding completion phrasing to paper over uncertainty -- default to surfacing uncertainty, not hiding it",
@@ -476,7 +508,7 @@
476
508
  "body": null
477
509
  },
478
510
  {
479
- "id": "coding-053",
511
+ "id": "coding-057",
480
512
  "tier": "MUST_NOT",
481
513
  "domain": "coding",
482
514
  "text": "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",
@@ -484,7 +516,23 @@
484
516
  "body": null
485
517
  },
486
518
  {
487
- "id": "coding-054",
519
+ "id": "coding-058",
520
+ "tier": "MUST",
521
+ "domain": "coding",
522
+ "text": "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",
523
+ "path": "coding/coding.md",
524
+ "body": null
525
+ },
526
+ {
527
+ "id": "coding-059",
528
+ "tier": "MUST_NOT",
529
+ "domain": "coding",
530
+ "text": "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",
531
+ "path": "coding/coding.md",
532
+ "body": null
533
+ },
534
+ {
535
+ "id": "coding-060",
488
536
  "tier": "MUST",
489
537
  "domain": "coding",
490
538
  "text": "User input is NEVER placed in the system prompt; the system prompt is the trust boundary",
@@ -492,7 +540,7 @@
492
540
  "body": null
493
541
  },
494
542
  {
495
- "id": "coding-055",
543
+ "id": "coding-061",
496
544
  "tier": "MUST",
497
545
  "domain": "coding",
498
546
  "text": "External content is ALWAYS wrapped in explicit delimiters (`<user_input>`, `<document>`, `<tool_result>`) and surfaces its trust tier",
@@ -500,7 +548,7 @@
500
548
  "body": null
501
549
  },
502
550
  {
503
- "id": "coding-056",
551
+ "id": "coding-062",
504
552
  "tier": "MUST",
505
553
  "domain": "coding",
506
554
  "text": "Tool call arguments are validated against a schema BEFORE execution (the LLM is a confused deputy)",
@@ -508,7 +556,7 @@
508
556
  "body": null
509
557
  },
510
558
  {
511
- "id": "coding-057",
559
+ "id": "coding-063",
512
560
  "tier": "MUST",
513
561
  "domain": "coding",
514
562
  "text": "LLM outputs are validated against expected schemas before being acted upon (no eval-of-output, no shell-of-output, no SQL-of-output)",
@@ -516,7 +564,7 @@
516
564
  "body": null
517
565
  },
518
566
  {
519
- "id": "coding-058",
567
+ "id": "coding-064",
520
568
  "tier": "MUST_NOT",
521
569
  "domain": "coding",
522
570
  "text": "MUST NOT write LLM outputs back into the retrieval corpus in the same session without validation (RAG poisoning vector)",
@@ -524,7 +572,7 @@
524
572
  "body": null
525
573
  },
526
574
  {
527
- "id": "coding-059",
575
+ "id": "coding-065",
528
576
  "tier": "MUST",
529
577
  "domain": "coding",
530
578
  "text": "No fixes without root-cause investigation first (the Iron Law)",
@@ -532,7 +580,7 @@
532
580
  "body": null
533
581
  },
534
582
  {
535
- "id": "coding-060",
583
+ "id": "coding-066",
536
584
  "tier": "MUST",
537
585
  "domain": "coding",
538
586
  "text": "Reproduce the failure consistently before proposing a fix — a non-reproducible bug is not yet understood",
@@ -540,7 +588,7 @@
540
588
  "body": null
541
589
  },
542
590
  {
543
- "id": "coding-061",
591
+ "id": "coding-067",
544
592
  "tier": "MUST",
545
593
  "domain": "coding",
546
594
  "text": "Every factual claim cites evidence; an uncited claim is a `[HYPOTHESIS]`, not a finding (evidence before narrative)",
@@ -548,7 +596,7 @@
548
596
  "body": null
549
597
  },
550
598
  {
551
- "id": "coding-062",
599
+ "id": "coding-068",
552
600
  "tier": "MUST",
553
601
  "domain": "coding",
554
602
  "text": "Runtime/config values are proven from the runtime, never inferred from source code (config is not code)",
@@ -556,7 +604,7 @@
556
604
  "body": null
557
605
  },
558
606
  {
559
- "id": "coding-063",
607
+ "id": "coding-069",
560
608
  "tier": "MUST_NOT",
561
609
  "domain": "coding",
562
610
  "text": "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)",
@@ -564,7 +612,7 @@
564
612
  "body": null
565
613
  },
566
614
  {
567
- "id": "coding-064",
615
+ "id": "coding-070",
568
616
  "tier": "MUST",
569
617
  "domain": "coding",
570
618
  "text": "After 3 failed distinct fixes, STOP and escalate for architectural review (the 3-fix gate)",
@@ -572,7 +620,7 @@
572
620
  "body": null
573
621
  },
574
622
  {
575
- "id": "coding-065",
623
+ "id": "coding-071",
576
624
  "tier": "MUST",
577
625
  "domain": "coding",
578
626
  "text": "Use Task ([go-task](https://taskfile.dev)) for all repeatable operations",
@@ -580,7 +628,7 @@
580
628
  "body": null
581
629
  },
582
630
  {
583
- "id": "coding-066",
631
+ "id": "coding-072",
584
632
  "tier": "MUST",
585
633
  "domain": "coding",
586
634
  "text": "If `task` not found, attempt to install go-task",
@@ -588,7 +636,7 @@
588
636
  "body": null
589
637
  },
590
638
  {
591
- "id": "coding-067",
639
+ "id": "coding-073",
592
640
  "tier": "MUST",
593
641
  "domain": "coding",
594
642
  "text": "If installation fails, stop and ask user for help",
@@ -596,7 +644,7 @@
596
644
  "body": null
597
645
  },
598
646
  {
599
- "id": "coding-068",
647
+ "id": "coding-074",
600
648
  "tier": "MUST",
601
649
  "domain": "coding",
602
650
  "text": "Before changing shared code, identify affected downstream modules/files",
@@ -604,7 +652,7 @@
604
652
  "body": null
605
653
  },
606
654
  {
607
- "id": "coding-069",
655
+ "id": "coding-075",
608
656
  "tier": "SHOULD",
609
657
  "domain": "coding",
610
658
  "text": "Prefer additive changes (new functions, fields with defaults) over breaking renames",
@@ -612,7 +660,7 @@
612
660
  "body": null
613
661
  },
614
662
  {
615
- "id": "coding-070",
663
+ "id": "coding-076",
616
664
  "tier": "MUST",
617
665
  "domain": "coding",
618
666
  "text": "Make small, reversible changes",
@@ -620,7 +668,7 @@
620
668
  "body": null
621
669
  },
622
670
  {
623
- "id": "coding-071",
671
+ "id": "coding-077",
624
672
  "tier": "MUST",
625
673
  "domain": "coding",
626
674
  "text": "Explain impact and migration path for breaking changes",
@@ -628,7 +676,7 @@
628
676
  "body": null
629
677
  },
630
678
  {
631
- "id": "coding-072",
679
+ "id": "coding-078",
632
680
  "tier": "MUST",
633
681
  "domain": "coding",
634
682
  "text": "Assume production impact unless stated otherwise",
@@ -636,7 +684,7 @@
636
684
  "body": null
637
685
  },
638
686
  {
639
- "id": "coding-073",
687
+ "id": "coding-079",
640
688
  "tier": "MUST",
641
689
  "domain": "coding",
642
690
  "text": "Call out risk when touching: auth, billing, data, APIs, build systems",
@@ -644,7 +692,7 @@
644
692
  "body": null
645
693
  },
646
694
  {
647
- "id": "coding-074",
695
+ "id": "coding-080",
648
696
  "tier": "MUST_NOT",
649
697
  "domain": "coding",
650
698
  "text": "Silent breaking behavior",
@@ -652,7 +700,7 @@
652
700
  "body": null
653
701
  },
654
702
  {
655
- "id": "coding-075",
703
+ "id": "coding-081",
656
704
  "tier": "SHOULD",
657
705
  "domain": "coding",
658
706
  "text": "Test changes in staging/dev environment when possible",
@@ -660,7 +708,7 @@
660
708
  "body": null
661
709
  },
662
710
  {
663
- "id": "coding-076",
711
+ "id": "coding-082",
664
712
  "tier": "SHOULD",
665
713
  "domain": "coding",
666
714
  "text": "Create both:",
@@ -668,7 +716,7 @@
668
716
  "body": null
669
717
  },
670
718
  {
671
- "id": "coding-077",
719
+ "id": "coding-083",
672
720
  "tier": "MUST",
673
721
  "domain": "coding",
674
722
  "text": "Check [PROJECT.md](../../PROJECT.md) for project-specific overrides",
@@ -676,7 +724,7 @@
676
724
  "body": null
677
725
  },
678
726
  {
679
- "id": "coding-078",
727
+ "id": "coding-084",
680
728
  "tier": "SHOULD",
681
729
  "domain": "coding",
682
730
  "text": "Inspect project config (package.json, pyproject.toml, etc.) for available scripts",
@@ -684,7 +732,7 @@
684
732
  "body": null
685
733
  },
686
734
  {
687
- "id": "coding-079",
735
+ "id": "coding-085",
688
736
  "tier": "MUST",
689
737
  "domain": "coding",
690
738
  "text": "Follow project-specific testing, coverage, and quality requirements",
@@ -692,7 +740,7 @@
692
740
  "body": null
693
741
  },
694
742
  {
695
- "id": "coding-080",
743
+ "id": "coding-086",
696
744
  "tier": "MUST_NOT",
697
745
  "domain": "coding",
698
746
  "text": "Secrets in code or version control",
@@ -700,7 +748,7 @@
700
748
  "body": null
701
749
  },
702
750
  {
703
- "id": "coding-081",
751
+ "id": "coding-087",
704
752
  "tier": "MUST_NOT",
705
753
  "domain": "coding",
706
754
  "text": "Claiming checks passed without running them",
@@ -708,7 +756,7 @@
708
756
  "body": null
709
757
  },
710
758
  {
711
- "id": "coding-082",
759
+ "id": "coding-088",
712
760
  "tier": "MUST_NOT",
713
761
  "domain": "coding",
714
762
  "text": "Single files mixing multiple responsibilities (large line count, e.g. >1000 lines, is a trigger to check cohesion — not a defect by itself; #1488)",
@@ -716,7 +764,7 @@
716
764
  "body": null
717
765
  },
718
766
  {
719
- "id": "coding-083",
767
+ "id": "coding-089",
720
768
  "tier": "MUST_NOT",
721
769
  "domain": "coding",
722
770
  "text": "Skipping quality checks",
@@ -724,7 +772,7 @@
724
772
  "body": null
725
773
  },
726
774
  {
727
- "id": "coding-084",
775
+ "id": "coding-090",
728
776
  "tier": "MUST_NOT",
729
777
  "domain": "coding",
730
778
  "text": "Breaking changes without explicit approval",
@@ -732,7 +780,7 @@
732
780
  "body": null
733
781
  },
734
782
  {
735
- "id": "coding-085",
783
+ "id": "coding-091",
736
784
  "tier": "MUST_NOT",
737
785
  "domain": "coding",
738
786
  "text": "Using `grep` command when `rg` or Warp grep available",
@@ -740,7 +788,7 @@
740
788
  "body": null
741
789
  },
742
790
  {
743
- "id": "coding-086",
791
+ "id": "coding-092",
744
792
  "tier": "MUST_NOT",
745
793
  "domain": "coding",
746
794
  "text": "Implementing code without tests",
@@ -748,7 +796,7 @@
748
796
  "body": null
749
797
  },
750
798
  {
751
- "id": "coding-087",
799
+ "id": "coding-093",
752
800
  "tier": "MUST_NOT",
753
801
  "domain": "coding",
754
802
  "text": "Claiming \"done\" before running test:coverage",
@@ -756,7 +804,7 @@
756
804
  "body": null
757
805
  },
758
806
  {
759
- "id": "coding-088",
807
+ "id": "coding-094",
760
808
  "tier": "MUST_NOT",
761
809
  "domain": "coding",
762
810
  "text": "Ignoring coverage drops",
@@ -764,7 +812,7 @@
764
812
  "body": null
765
813
  },
766
814
  {
767
- "id": "coding-089",
815
+ "id": "coding-095",
768
816
  "tier": "MUST_NOT",
769
817
  "domain": "coding",
770
818
  "text": "Weak types (`any`, `interface{}`, untyped `object`) where concrete types are knowable",
@@ -772,7 +820,7 @@
772
820
  "body": null
773
821
  },
774
822
  {
775
- "id": "coding-090",
823
+ "id": "coding-096",
776
824
  "tier": "MUST_NOT",
777
825
  "domain": "coding",
778
826
  "text": "Dead code: unused functions, unreachable branches, stale feature flags, commented-out blocks",
@@ -780,7 +828,7 @@
780
828
  "body": null
781
829
  },
782
830
  {
783
- "id": "coding-091",
831
+ "id": "coding-097",
784
832
  "tier": "MUST_NOT",
785
833
  "domain": "coding",
786
834
  "text": "Error hiding: empty catch blocks, silent fallbacks, swallowed exceptions",
@@ -788,7 +836,7 @@
788
836
  "body": null
789
837
  },
790
838
  {
791
- "id": "coding-092",
839
+ "id": "coding-098",
792
840
  "tier": "MUST_NOT",
793
841
  "domain": "coding",
794
842
  "text": "Circular imports between modules",
@@ -796,7 +844,7 @@
796
844
  "body": null
797
845
  },
798
846
  {
799
- "id": "coding-093",
847
+ "id": "coding-099",
800
848
  "tier": "MUST_NOT",
801
849
  "domain": "coding",
802
850
  "text": "Duplicate logic across 2+ call sites without shared abstraction",
@@ -804,7 +852,7 @@
804
852
  "body": null
805
853
  },
806
854
  {
807
- "id": "coding-094",
855
+ "id": "coding-100",
808
856
  "tier": "MUST_NOT",
809
857
  "domain": "coding",
810
858
  "text": "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)",
@@ -812,42 +860,26 @@
812
860
  "body": null
813
861
  },
814
862
  {
815
- "id": "coding-095",
863
+ "id": "coding-101",
816
864
  "tier": "MUST_NOT",
817
865
  "domain": "coding",
818
- "text": "Averaging contradicting codebase patterns: writing new code that satisfies both of two conflicting patterns simultaneously (#1005 -- see `hygiene.md` `## Surface Conflicts`)",
819
- "path": "coding/coding.md",
820
- "body": null
821
- },
822
- {
823
- "id": "coding-096",
824
- "tier": "MUST_NOT",
825
- "domain": "coding",
826
- "text": "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`)",
827
- "path": "coding/coding.md",
828
- "body": null
829
- },
830
- {
831
- "id": "coding-097",
832
- "tier": "MUST",
833
- "domain": "coding",
834
- "text": "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 Fail Loud (#1006)",
866
+ "text": "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)",
835
867
  "path": "coding/coding.md",
836
868
  "body": null
837
869
  },
838
870
  {
839
- "id": "coding-098",
871
+ "id": "coding-102",
840
872
  "tier": "MUST_NOT",
841
873
  "domain": "coding",
842
- "text": "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 (#2899 / #1006)",
874
+ "text": "Averaging contradicting codebase patterns: writing new code that satisfies both of two conflicting patterns simultaneously (#1005 -- see `hygiene.md` `## Surface Conflicts`)",
843
875
  "path": "coding/coding.md",
844
876
  "body": null
845
877
  },
846
878
  {
847
- "id": "coding-099",
879
+ "id": "coding-103",
848
880
  "tier": "MUST_NOT",
849
881
  "domain": "coding",
850
- "text": "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)",
882
+ "text": "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`)",
851
883
  "path": "coding/coding.md",
852
884
  "body": null
853
885
  },