@gonrocca/zero-pi 0.1.51 → 0.1.52

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/LICENSE +0 -0
  2. package/README.md +23 -0
  3. package/assets/preview.png +0 -0
  4. package/extensions/autotune-extension.ts +0 -0
  5. package/extensions/autotune.ts +0 -0
  6. package/extensions/conversation-resume.ts +0 -0
  7. package/extensions/gh-runner.ts +0 -0
  8. package/extensions/git-runner.ts +0 -0
  9. package/extensions/pr-body.ts +0 -0
  10. package/extensions/provider-guard-extension.ts +0 -0
  11. package/extensions/provider-guard.ts +0 -0
  12. package/extensions/scan-guard-extension.ts +0 -0
  13. package/extensions/scan-guard.ts +0 -0
  14. package/extensions/sdd-agents.ts +33 -1
  15. package/extensions/sdd-config.ts +25 -0
  16. package/extensions/sdd-links.ts +0 -0
  17. package/extensions/spec-merge-extension.ts +0 -0
  18. package/extensions/spec-merge.ts +0 -0
  19. package/extensions/win-tree-kill.ts +0 -0
  20. package/extensions/working-phrases.ts +0 -0
  21. package/extensions/zero-archive-extension.ts +0 -0
  22. package/extensions/zero-banner.ts +0 -0
  23. package/extensions/zero-branch-extension.ts +0 -0
  24. package/extensions/zero-diff-extension.ts +0 -0
  25. package/extensions/zero-git-validate-extension.ts +0 -0
  26. package/extensions/zero-issue-extension.ts +0 -0
  27. package/extensions/zero-models-picker.ts +0 -0
  28. package/extensions/zero-models.ts +0 -0
  29. package/extensions/zero-pr-extension.ts +0 -0
  30. package/extensions/zero-status-extension.ts +0 -0
  31. package/extensions/zero-status.ts +0 -0
  32. package/extensions/zero-statusline.ts +0 -0
  33. package/extensions/zero-validate-extension.ts +0 -0
  34. package/extensions/zero-validate.ts +0 -0
  35. package/package.json +1 -1
  36. package/prompts/forge.md +6 -0
  37. package/prompts/orchestrator.md +23 -0
  38. package/prompts/phases/build.md +30 -0
  39. package/prompts/phases/explore.md +0 -0
  40. package/prompts/phases/plan.md +23 -0
  41. package/prompts/phases/veredicto.md +23 -0
  42. package/prompts/support/strict-tdd-verify.md +193 -0
  43. package/prompts/support/strict-tdd.md +333 -0
  44. package/skills/sdd-routing/SKILL.md +0 -0
  45. package/themes/zero-sdd.json +0 -0
package/LICENSE CHANGED
File without changes
package/README.md CHANGED
@@ -56,6 +56,14 @@ The verdict is `pasa` (done), `corregir` (re-run build), or `replantear`
56
56
  without a `pasa`, the run stops and is reported as **not verified**.
57
57
  `/forge --continue [slug]` resumes an interrupted run.
58
58
 
59
+ **Build runs test-first.** By default the build phase follows a strict TDD
60
+ cycle — RED → GREEN → TRIANGULATE → REFACTOR — and records a **TDD Cycle
61
+ Evidence** table; veredicto audits that evidence (tests exist, are really green,
62
+ assertions verify real behavior) and returns `corregir` if the discipline
63
+ slipped. It engages only when a test runner exists and the change touches code,
64
+ so docs/config-only work degrades gracefully. Opt a project out with
65
+ `tdd.mode: "off"` in `.sdd/config.json` (see *Configuration*).
66
+
59
67
  The run speaks **Spanish**, in a bounded, low-noise format — one short summary
60
68
  per phase, naming the model that phase runs on, no raw tool output. Or just
61
69
  describe the work and say "hacelo con sdd": the `sdd-routing` skill routes it
@@ -65,6 +73,7 @@ into `/forge` for you.
65
73
 
66
74
  | Feature | What it does |
67
75
  | ------- | ------------ |
76
+ | **Strict TDD** | The build phase drives RED → GREEN → TRIANGULATE → REFACTOR with a TDD Cycle Evidence table; veredicto audits it. On by default, runtime-gated on a test runner; `tdd.mode: "off"` disables it. |
68
77
  | **`/zero-models`** | Pick the model + provider for each SDD phase — a boxed-window picker, or set one directly. |
69
78
  | **Autotune** | Learns which model fits each phase from your run history and re-tunes itself. |
70
79
  | **`/zero-sync` / `/zero-archive`** | Folds each run's spec delta into a canonical, project-wide spec store and archives approved runs. |
@@ -160,6 +169,20 @@ zero-pi keeps its state in `~/.pi/zero.json` (per-phase models + autotune mode)
160
169
  and `~/.pi/zero-runs.jsonl` (the run-metrics log); per-project artifacts live
161
170
  under `.sdd/`. Set `ZERO_RESUME=off` to disable the conversation-resume note.
162
171
 
172
+ `.sdd/config.json` carries the per-project git and TDD settings:
173
+
174
+ ```json
175
+ {
176
+ "git": { "branchPrefix": "sdd/", "numbering": false, "autoCommit": false, "commitStyle": "conventional", "baseBranch": "main" },
177
+ "tdd": { "mode": "strict", "testCommand": "" }
178
+ }
179
+ ```
180
+
181
+ `tdd.mode` defaults to `"strict"` (the build phase runs test-first; veredicto
182
+ audits the TDD evidence) and accepts `"off"` to disable the discipline.
183
+ `tdd.testCommand` overrides the auto-detected test runner the TDD cycle invokes;
184
+ leave it empty to let the build/veredicto phases detect it from the project.
185
+
163
186
  ## Continuous integration
164
187
 
165
188
  The `.github/workflows/zero-pi-ci.yml` workflow runs on every push to `main` and
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -11,7 +11,7 @@
11
11
  // the per-phase models in `~/.pi/zero.json`. The files are regenerated every
12
12
  // load, so they stay in sync with the prompts and with `/zero-models`.
13
13
 
14
- import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
14
+ import { copyFileSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
15
15
  import { homedir } from "node:os";
16
16
  import { dirname, join } from "node:path";
17
17
  import { fileURLToPath } from "node:url";
@@ -20,6 +20,20 @@ import { fileURLToPath } from "node:url";
20
20
  export const PHASES = ["explore", "plan", "build", "veredicto"] as const;
21
21
  export type Phase = (typeof PHASES)[number];
22
22
 
23
+ /**
24
+ * The Strict TDD support modules, copied verbatim from `prompts/support/` to a
25
+ * stable directory beside the generated agents so the `zero-build` /
26
+ * `zero-veredicto` sub-agents can `read` them at runtime. The sub-agents are
27
+ * generated with `inheritSkills: false`, so the phase prompt body is the only
28
+ * channel that can point them at these files — see `supportModulesDir()`.
29
+ */
30
+ export const SUPPORT_MODULES = ["strict-tdd.md", "strict-tdd-verify.md"] as const;
31
+
32
+ /** Absolute path of the runtime support dir the phase prompts reference. */
33
+ export function supportModulesDir(): string {
34
+ return join(homedir(), ".pi", "agent", "agents", "zero", "support");
35
+ }
36
+
23
37
  /**
24
38
  * Split a phase prompt into its `description` (from `---` frontmatter) and its
25
39
  * body. A prompt with no frontmatter yields an empty description and the whole
@@ -109,6 +123,7 @@ export default function register(_pi?: unknown): void {
109
123
  try {
110
124
  const here = dirname(fileURLToPath(import.meta.url)); // <pkg>/extensions
111
125
  const phasesDir = join(here, "..", "prompts", "phases");
126
+ const supportSrcDir = join(here, "..", "prompts", "support");
112
127
  const agentsDir = join(homedir(), ".pi", "agent", "agents", "zero");
113
128
  mkdirSync(agentsDir, { recursive: true });
114
129
 
@@ -122,6 +137,23 @@ export default function register(_pi?: unknown): void {
122
137
  // A single phase failing must not block the other three.
123
138
  }
124
139
  }
140
+
141
+ // Stage the Strict TDD support modules next to the agents so `zero-build`
142
+ // and `zero-veredicto` can read them at runtime. A copy failure is
143
+ // non-fatal: the build/veredicto prompts carry an inline fallback contract.
144
+ try {
145
+ const supportDir = supportModulesDir();
146
+ mkdirSync(supportDir, { recursive: true });
147
+ for (const mod of SUPPORT_MODULES) {
148
+ try {
149
+ copyFileSync(join(supportSrcDir, mod), join(supportDir, mod));
150
+ } catch {
151
+ // One module failing must not block the other.
152
+ }
153
+ }
154
+ } catch {
155
+ // Support staging is best-effort; the inline fallback covers absence.
156
+ }
125
157
  } catch {
126
158
  // Sub-agent provisioning must never break a pi session.
127
159
  }
@@ -9,10 +9,30 @@ export interface SddConfig {
9
9
  commitStyle: "conventional" | "plain";
10
10
  baseBranch: string;
11
11
  };
12
+ /**
13
+ * Strict TDD discipline for the build/veredicto phases.
14
+ *
15
+ * `mode`:
16
+ * - `"strict"` (default) — the build phase follows RED → GREEN →
17
+ * TRIANGULATE → REFACTOR and emits a TDD Cycle Evidence table; veredicto
18
+ * audits it. The discipline is **runtime-gated**: the phase prompts only
19
+ * engage it when a test runner is actually available and the change touches
20
+ * code — a docs/config-only change or a project with no test runner
21
+ * degrades gracefully instead of failing.
22
+ * - `"off"` — no TDD ceremony; the build phase tests where practical only.
23
+ *
24
+ * `testCommand` is an optional explicit override of the test runner the TDD
25
+ * cycle invokes; empty means the phase auto-detects it from the project.
26
+ */
27
+ tdd: {
28
+ mode: "strict" | "off";
29
+ testCommand: string;
30
+ };
12
31
  }
13
32
 
14
33
  export const DEFAULT_SDD_CONFIG: SddConfig = {
15
34
  git: { branchPrefix: "sdd/", numbering: false, autoCommit: false, commitStyle: "conventional", baseBranch: "main" },
35
+ tdd: { mode: "strict", testCommand: "" },
16
36
  };
17
37
 
18
38
  function asObject(value: unknown): Record<string, unknown> {
@@ -26,6 +46,7 @@ export function loadSddConfig(root = process.cwd()): SddConfig {
26
46
  try { parsed = asObject(JSON.parse(readFileSync(path, "utf8"))); }
27
47
  catch (err) { throw new Error(`invalid .sdd/config.json: ${err instanceof Error ? err.message : String(err)}`); }
28
48
  const git = asObject(parsed.git);
49
+ const tdd = asObject(parsed.tdd);
29
50
  return {
30
51
  git: {
31
52
  branchPrefix: typeof git.branchPrefix === "string" ? git.branchPrefix : DEFAULT_SDD_CONFIG.git.branchPrefix,
@@ -34,5 +55,9 @@ export function loadSddConfig(root = process.cwd()): SddConfig {
34
55
  commitStyle: git.commitStyle === "plain" ? "plain" : DEFAULT_SDD_CONFIG.git.commitStyle,
35
56
  baseBranch: typeof git.baseBranch === "string" ? git.baseBranch : DEFAULT_SDD_CONFIG.git.baseBranch,
36
57
  },
58
+ tdd: {
59
+ mode: tdd.mode === "off" ? "off" : DEFAULT_SDD_CONFIG.tdd.mode,
60
+ testCommand: typeof tdd.testCommand === "string" ? tdd.testCommand : DEFAULT_SDD_CONFIG.tdd.testCommand,
61
+ },
37
62
  };
38
63
  }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gonrocca/zero-pi",
3
- "version": "0.1.51",
3
+ "version": "0.1.52",
4
4
  "description": "zero-pi — an installable layer for pi (pi.dev): the zero spec-driven development workflow (explore → plan → build → veredicto) with per-phase model autotune and token-efficient batched builds. Adds capability to pi without modifying pi.",
5
5
  "type": "module",
6
6
  "keywords": [
package/prompts/forge.md CHANGED
@@ -14,6 +14,12 @@ claim success unless veredicto returned `pasa`.
14
14
  If the request begins with `--continue [slug]`, resume that unfinished run from
15
15
  its `.sdd/<slug>/` artifacts instead of starting fresh.
16
16
 
17
+ **Strict TDD by default.** Follow the orchestrator's `## Strict TDD forwarding`:
18
+ build runs test-first (RED → GREEN → TRIANGULATE → REFACTOR) and emits a TDD
19
+ Cycle Evidence table whenever a test runner exists and the work touches code;
20
+ veredicto audits that evidence and returns `corregir` if it fails. Set
21
+ `tdd.mode: "off"` in `.sdd/config.json` to opt a project out.
22
+
17
23
  **Output and language.** Follow the orchestrator's `## Language Boundary` and
18
24
  `## Output Contract`: user-facing chat in Spanish (natural Rioplatense voseo),
19
25
  the bounded per-phase summary, no raw tool output, no agent listings, no
@@ -152,6 +152,29 @@ phase (re-batching whatever tasks its defects reopened) as the next round.
152
152
  **Resume is unaffected.** Each batch marks its tasks `[x]` as they land, so an
153
153
  interrupted batched build resumes from the first `[ ]` task with no new state.
154
154
 
155
+ ## Strict TDD forwarding
156
+
157
+ zero runs build test-first by default. Before the **build** and **veredicto**
158
+ phases, resolve the run's TDD mode once and forward it explicitly — never rely
159
+ on the sub-agent to discover it alone.
160
+
161
+ - Read `.sdd/config.json` at run start. `tdd.mode` is `"strict"` by default
162
+ (absent file or field = strict); `"off"` disables the discipline.
163
+ - Strict TDD only *engages* when a test runner exists (`tdd.testCommand`, or one
164
+ the phase detects from the project) and the work touches code — the phase
165
+ prompts gate on this and degrade gracefully for docs/config-only changes or
166
+ projects with no runner. You do not need to pre-check the runner; just forward
167
+ the mode.
168
+ - When mode is strict, add one line to the `zero-build` and `zero-veredicto`
169
+ briefs: `Strict TDD mode: strict (test command: <cmd or "auto-detect">).
170
+ Follow RED → GREEN → TRIANGULATE → REFACTOR and record the TDD Cycle Evidence
171
+ table.` When mode is `off`, forward `Strict TDD mode: off`.
172
+ - The build writes its evidence to `.sdd/<slug>/tdd-evidence.md`; veredicto
173
+ audits it. Reference that artifact by path in the briefs — never paste it.
174
+ - A veredicto that fails the TDD audit (missing evidence, a reported-green test
175
+ that now fails, or a CRITICAL assertion violation) returns `corregir`, which
176
+ re-runs build as the next round exactly like any other defect list.
177
+
155
178
  ## Model configuration
156
179
 
157
180
  The per-phase model assignments live in `~/.pi/zero.json`: `models` maps each
@@ -26,6 +26,36 @@ then proceed — never fall back to scanning the whole tree.
26
26
  Implement the planned tasks in order, test-first where practical. Keep every
27
27
  change within the plan's scope — do not expand it on your own initiative.
28
28
 
29
+ ## Strict TDD gate
30
+
31
+ Before writing code, resolve whether **Strict TDD Mode** is active for this run.
32
+ It is active when **all three** hold:
33
+
34
+ 1. **Mode is on.** Read `.sdd/config.json`; treat `tdd.mode` as `"strict"` when
35
+ the file is absent or the field is missing (strict is the default). If
36
+ `tdd.mode` is `"off"`, Strict TDD is disabled — skip to *Standard mode* below.
37
+ 2. **A test runner exists.** Use `tdd.testCommand` from `.sdd/config.json` when
38
+ set; otherwise detect one from the project (`package.json` scripts,
39
+ `pyproject.toml`, `go.mod`, a Makefile target, etc.). If no test runner can
40
+ be found, Strict TDD cannot run — note it as a risk and use *Standard mode*.
41
+ 3. **The batch touches code.** A docs-, copy-, or config-only batch has nothing
42
+ to drive with tests — note it and use *Standard mode* for that batch.
43
+
44
+ When all three hold, **Strict TDD Mode is active**. Read the support module
45
+ `~/.pi/agent/agents/zero/support/strict-tdd.md` and follow it for every task in
46
+ your batch: RED → GREEN → TRIANGULATE → REFACTOR, never production code before a
47
+ failing test, run the focused test on every GREEN, and emit the **TDD Cycle
48
+ Evidence** table to `.sdd/<slug>/tdd-evidence.md` and in your return envelope. If
49
+ that support file is missing, do not silently drop the discipline: follow the
50
+ RED → GREEN → TRIANGULATE → REFACTOR contract and the TDD Cycle Evidence table
51
+ from memory, and report the missing module as a risk.
52
+
53
+ ## Standard mode
54
+
55
+ When Strict TDD is disabled, unavailable, or the batch is code-free, implement
56
+ the assigned tasks test-first where practical, update the task checkboxes, and
57
+ record the verification evidence — no TDD Cycle Evidence table is required.
58
+
29
59
  **Scope to your batch.** When the brief names a batch — a set or contiguous
30
60
  range of task numbers — implement exactly those tasks, mark each `[x]`, and
31
61
  **return**; do not continue into later unchecked tasks (the orchestrator drives
File without changes
@@ -84,6 +84,29 @@ Rules:
84
84
  - `evidence:` is mandatory and names a concrete verification command or artifact.
85
85
  - Keep `## Review Workload` present and synchronized with the task list.
86
86
 
87
+ ## TDD-shaped tasks
88
+
89
+ Unless the project sets `tdd.mode: "off"` in `.sdd/config.json`, the build phase
90
+ runs under **Strict TDD** whenever a test runner exists and the task touches
91
+ code. Shape the tasks so that discipline is natural rather than bolted on:
92
+
93
+ - For every code task, list its **test file alongside the production file** in
94
+ `files:` (mark a brand-new test `(new)`), so RED → GREEN has a home from the
95
+ start. A task that changes behavior with no test file in its `files:` list is
96
+ under-specified — add one.
97
+ - Make `evidence:` name the **focused test command** that proves the task
98
+ (`npm test -- <file>`, `pytest <file>`, `go test ./pkg -run <Name>`), not a
99
+ vague "works" — the build runs exactly that during the cycle and veredicto
100
+ re-runs it.
101
+ - Keep each task small enough that one RED → GREEN → TRIANGULATE → REFACTOR
102
+ cycle covers it; if a task needs several unrelated tests, split it.
103
+ - Pure-structural tasks (a constant, a type export, a config value) need no
104
+ test — say so in the task `detail:` so the build phase can note
105
+ "Triangulation skipped" without guessing.
106
+
107
+ This is guidance for the task shape only; the build phase owns the actual RED →
108
+ GREEN cycle and the TDD Cycle Evidence table.
109
+
87
110
  ## Constitution / Steering check
88
111
 
89
112
  Before finalizing tasks, check project steering/constitution files when present (`.sdd/constitution.md`, `.sdd/steering.md`, `.kiro/steering/*`, or project equivalents). If absent, mark `n/a`; absence is not a blocker. Include this table in `design.md` or `tasks.md`:
@@ -39,6 +39,29 @@ Review the build adversarially, with a fresh perspective. Check it against the
39
39
  plan's requirements, run the tests yourself, and look for gaps, regressions,
40
40
  and unmet acceptance criteria.
41
41
 
42
+ ## Strict TDD audit
43
+
44
+ Resolve whether **Strict TDD Mode** governed this run, by the same gate the
45
+ build phase used: `tdd.mode` in `.sdd/config.json` is `"strict"` (the default
46
+ when the file or field is absent) **and** a test runner exists
47
+ (`tdd.testCommand` or one detected from the project) **and** the change touches
48
+ code. A `.sdd/<slug>/tdd-evidence.md` file or a TDD Cycle Evidence table in the
49
+ build result also signals it was active.
50
+
51
+ When Strict TDD governed the run, read the support module
52
+ `~/.pi/agent/agents/zero/support/strict-tdd-verify.md` and apply it: confirm the
53
+ TDD Cycle Evidence table exists, cross-reference every reported test file
54
+ against the codebase, run the listed tests yourself to confirm GREEN still
55
+ holds, and audit assertion quality (no tautologies, ghost loops, lone type-only
56
+ assertions, smoke-only tests, or implementation-detail/CSS assertions). A
57
+ missing evidence table, a reported-green test that now fails, or a CRITICAL
58
+ assertion violation is grounds for **`corregir`**, not `pasa`. If that support
59
+ file is missing, perform the same checks from memory and note the missing module
60
+ as a risk — do not skip the TDD audit.
61
+
62
+ When Strict TDD did not govern the run (mode `off`, no test runner, or a
63
+ code-free change), skip the TDD audit and review on the standard criteria below.
64
+
42
65
  ## Constitution / Steering gate
43
66
 
44
67
  Re-check the plan's Constitution/Steering table before choosing a verdict. If a
@@ -0,0 +1,193 @@
1
+ # Strict TDD Module — Veredicto Phase
2
+
3
+ > **This module governs the veredicto phase ONLY when Strict TDD Mode is active
4
+ > AND a test runner is available.** The veredicto prompt already resolved both
5
+ > conditions before pointing you here. If you are reading this, follow every
6
+ > instruction.
7
+
8
+ ## TDD Verification Philosophy
9
+
10
+ When Strict TDD Mode is active, the review goes beyond "does the code work?" to
11
+ "was the code built correctly?" — meaning: was TDD actually followed? The build
12
+ phase reports TDD evidence; your job is to validate that evidence against
13
+ reality. A failed TDD audit is a **`corregir`** verdict, not `pasa`.
14
+
15
+ ## Step A — TDD Compliance Check
16
+
17
+ Read the build's **TDD Cycle Evidence** table — from
18
+ `.sdd/<slug>/tdd-evidence.md` and/or the build's return envelope — and verify
19
+ TDD was actually followed:
20
+
21
+ ```
22
+ FOR EACH task row in the TDD Cycle Evidence table:
23
+ ├── RED column:
24
+ │ ├── Must say "✅ Written"
25
+ │ ├── Verify: the named test file EXISTS in the codebase
26
+ │ └── Flag: CRITICAL if the test file does not exist
27
+
28
+ ├── GREEN column:
29
+ │ ├── Must say "✅ Passed"
30
+ │ ├── Cross-reference with your own test run (Step C):
31
+ │ │ └── The listed test file must PASS when YOU run it
32
+ │ └── Flag: CRITICAL if the test fails now (was it really green?)
33
+
34
+ ├── TRIANGULATE column:
35
+ │ ├── "✅ N cases" → verify N test cases exist in the file
36
+ │ ├── "➖ Single" → verify the spec truly has only one scenario
37
+ │ └── Flag: WARNING if the spec has multiple scenarios but only 1 test case
38
+
39
+ ├── SAFETY NET column:
40
+ │ ├── "✅ N/N" → existing tests were run before modification (good)
41
+ │ ├── "N/A (new)" → verify the file was actually NEW, not modified
42
+ │ └── Flag: WARNING if a modified file shows "N/A"
43
+
44
+ └── REFACTOR column:
45
+ └── Not strictly verifiable (subjective) — trust the report
46
+
47
+ If NO "TDD Cycle Evidence" table is found:
48
+ └── Flag: CRITICAL — the build did not report TDD evidence while Strict TDD was
49
+ active. This alone is grounds for a `corregir` verdict.
50
+
51
+ Summary: "{N}/{total} tasks have complete TDD evidence".
52
+ ```
53
+
54
+ ## Step B — Test Layer Validation
55
+
56
+ Classify every test file related to this change by its testing layer:
57
+
58
+ ```
59
+ ├── Unit test: a single function/class in isolation
60
+ │ └── Indicators: no render(), no page., no HTTP calls, mocked deps
61
+ ├── Integration test: component interaction or user behavior
62
+ │ └── Indicators: render(), screen., userEvent., testing-library imports
63
+ ├── E2E test: full system through a real browser/HTTP
64
+ │ └── Indicators: page.goto(), playwright/cypress imports, browser context
65
+ └── Unknown: cannot classify → report as-is
66
+
67
+ Report the distribution (Unit / Integration / E2E counts) and, for each spec
68
+ scenario, note which layer covers it. Flag as SUGGESTION (not blocking) if
69
+ critical business logic only has unit tests while higher-layer tools exist.
70
+ ```
71
+
72
+ ## Step C — Run the Tests Yourself
73
+
74
+ Run the relevant focused tests AND the full suite when available, exactly as
75
+ reported, and confirm GREEN is still true. Report the commands you ran and any
76
+ failures verbatim. A test that the build reported as ✅ but fails when you run
77
+ it is a CRITICAL discrepancy.
78
+
79
+ ## Step D — Changed File Coverage (if a coverage tool is available)
80
+
81
+ ```
82
+ IF a coverage tool is available:
83
+ ├── Run the coverage command
84
+ ├── Filter to ONLY files created/modified in this change
85
+ ├── Report per file: line %, branch %, uncovered line ranges
86
+ │ ├── ≥ 95% → ✅ Excellent
87
+ │ ├── ≥ 80% → ⚠️ Acceptable
88
+ │ └── < 80% → ⚠️ Low (list the uncovered lines)
89
+ └── Flag: WARNING (never CRITICAL) if a changed file is < 80%
90
+
91
+ IF NOT available:
92
+ └── "Coverage analysis skipped — no coverage tool detected" (not a failure).
93
+ ```
94
+
95
+ ## Step E — Assertion Quality Audit (MANDATORY)
96
+
97
+ Scan ALL test files created or modified by this change for trivial/meaningless
98
+ assertions:
99
+
100
+ ```
101
+ FOR EACH test file related to the change:
102
+ ├── Scan for BANNED patterns:
103
+ │ ├── Tautologies: expect(true).toBe(true), assert True, expect(1).toBe(1)
104
+ │ │ └── CRITICAL — the test proves NOTHING
105
+ │ ├── Orphan empty checks: expect(result).toEqual([]) / assert len(result) == 0
106
+ │ │ └── WARNING unless a companion test with the same setup asserts NON-EMPTY
107
+ │ ├── Type-only assertions used alone: toBeDefined(), not.toBeNull(), typeof
108
+ │ │ └── WARNING — OK only when COMBINED with a value assertion
109
+ │ ├── Assertions that never call production code (no call, no render, no request)
110
+ │ │ └── CRITICAL — the test exercises nothing
111
+ │ ├── Ghost loops: assertions inside for/forEach over queryAll/filter results
112
+ │ │ └── CRITICAL if the collection could be empty — the loop never runs
113
+ │ ├── Incomplete TDD cycle: passes because preconditions stop the code running
114
+ │ │ └── CRITICAL — the code path was never exercised
115
+ │ ├── Smoke-only: render() + toBeInTheDocument() with no behavioral assertion
116
+ │ │ └── WARNING — does not count toward TDD coverage
117
+ │ ├── Implementation-detail coupling: CSS classes, internal state, mock call counts
118
+ │ │ └── WARNING — tests must assert behavior, not implementation
119
+ │ └── Mock/assertion ratio: vi.mock()/jest.mock() count vs expect() count
120
+ │ └── WARNING if mocks > 2× assertions — wrong test layer
121
+
122
+ ├── For each violation: record file, line, the assertion, and why it's trivial.
123
+
124
+ └── Triangulation quality:
125
+ ├── If a behavior with multiple spec scenarios has only 1 test case → WARNING
126
+ └── If all cases assert the SAME trivial value (all empty arrays) → WARNING
127
+
128
+ Summary: "{N} trivial assertions found across {N} files".
129
+ ```
130
+
131
+ ## Step F — Quality Metrics (if tools available)
132
+
133
+ ```
134
+ IF a linter is available → run on changed files; report errors/warnings.
135
+ IF a type checker is available → run; filter to changed files; report type errors.
136
+ IF neither → "Quality metrics skipped — no tools detected" (not a failure).
137
+ ```
138
+
139
+ ## Verdict Mapping
140
+
141
+ Fold the TDD audit into the standard verdict:
142
+
143
+ - A missing TDD Cycle Evidence table, a CRITICAL assertion violation
144
+ (tautology, no-production-call, ghost loop, incomplete cycle), or a test that
145
+ fails when you run it → **`corregir`** with the specific defects named.
146
+ - WARNING-level findings (low coverage, smoke tests, mock-heavy, impl-detail
147
+ coupling, thin triangulation) do not by themselves force `corregir`, but list
148
+ them in the verdict reasoning so the next build round can address them.
149
+ - Coverage/quality-tool absence is never a failure — note it and move on.
150
+ - `pasa` requires: all evidence present, every reported GREEN actually green
151
+ when you run it, and no CRITICAL assertion violations.
152
+
153
+ ## Report Section (include in the verdict reasoning)
154
+
155
+ ```markdown
156
+ ### TDD Compliance
157
+ | Check | Result | Details |
158
+ |-------|--------|---------|
159
+ | TDD Evidence reported | ✅ / ❌ | Found in tdd-evidence.md / Missing |
160
+ | All tasks have tests | ✅ / ❌ | {N}/{total} tasks have test files |
161
+ | RED confirmed (tests exist) | ✅ / ⚠️ | {N}/{total} test files verified |
162
+ | GREEN confirmed (tests pass) | ✅ / ❌ | {N}/{total} pass on execution |
163
+ | Triangulation adequate | ✅ / ⚠️ / ➖ | {N} triangulated / {N} single-case |
164
+ | Safety Net for modified files | ✅ / ⚠️ | {N}/{total} had a safety net |
165
+
166
+ **TDD Compliance**: {N}/{total} checks passed
167
+
168
+ ### Test Layer Distribution
169
+ | Layer | Tests | Files | Tools |
170
+ |-------|-------|-------|-------|
171
+ | Unit | {N} | {N} | {tool} |
172
+ | Integration | {N} | {N} | {tool or "not installed"} |
173
+ | E2E | {N} | {N} | {tool or "not installed"} |
174
+
175
+ ### Assertion Quality
176
+ | File | Line | Assertion | Issue | Severity |
177
+ |------|------|-----------|-------|----------|
178
+ | ... | ... | ... | ... | ... |
179
+
180
+ **Assertion quality**: {N} CRITICAL, {N} WARNING
181
+ (or "✅ All assertions verify real behavior")
182
+ ```
183
+
184
+ ## Rules (Strict TDD Verify specific)
185
+
186
+ - ALWAYS check the TDD Cycle Evidence table — it is the primary artifact.
187
+ - ALWAYS cross-reference the reported test files against an actual run — never trust the report blindly.
188
+ - ALWAYS run the Assertion Quality Audit (Step E) — trivial tests are WORSE than missing tests.
189
+ - If no TDD evidence table exists while Strict TDD is active → CRITICAL → `corregir`.
190
+ - If a tautology assertion is found → CRITICAL → it MUST be rewritten → `corregir`.
191
+ - Coverage and quality metrics are informational — WARNING at most, never the sole cause of `corregir`.
192
+ - DO NOT fix issues — only report and choose the verdict. The build phase fixes on the `corregir` re-run.
193
+ - If coverage/quality tools are absent, say so cleanly and move on — never flag a missing tool as a failure.
@@ -0,0 +1,333 @@
1
+ # Strict TDD Module — Build Phase
2
+
3
+ > **This module governs the build phase ONLY when Strict TDD Mode is active AND
4
+ > a test runner is available.** The build prompt already resolved both
5
+ > conditions before pointing you here. If you are reading this, follow every
6
+ > instruction.
7
+
8
+ ## TDD Philosophy
9
+
10
+ TDD is not testing. TDD is **software design driven by tests**. You write a test
11
+ that describes what the code SHOULD do, then write the minimum code to make it
12
+ real. The tests design the API, the contracts, the behavior. Code is a side
13
+ effect of tests.
14
+
15
+ ### The Three Laws
16
+
17
+ 1. **Do NOT write production code** until you have a failing test.
18
+ 2. **Do NOT write more test** than is necessary to fail.
19
+ 3. **Do NOT write more code** than is necessary to pass the test.
20
+
21
+ ## TDD Implementation Cycle
22
+
23
+ For EVERY task assigned to your batch, follow this cycle strictly:
24
+
25
+ ```
26
+ FOR EACH TASK:
27
+ ├── 0. SAFETY NET (only if modifying existing files)
28
+ │ ├── Run existing tests for the files being modified
29
+ │ ├── Capture baseline: "{N} tests passing"
30
+ │ ├── If any FAIL → STOP, report as "pre-existing failure"
31
+ │ │ (do NOT fix pre-existing failures — report them in the return envelope)
32
+ │ └── This baseline proves you did not break what already worked
33
+
34
+ ├── 1. UNDERSTAND
35
+ │ ├── Read the task description and its `files:` / `evidence:` bullets
36
+ │ ├── Read the relevant spec.md scenarios (these ARE your acceptance criteria)
37
+ │ ├── Read the design.md decisions (these CONSTRAIN your approach)
38
+ │ ├── Read existing code and test patterns (match the style)
39
+ │ └── Determine the test layer (see "Choosing Test Layer" below)
40
+
41
+ ├── 2. RED — Write a failing test FIRST
42
+ │ ├── Write test(s) that describe the expected behavior from the spec
43
+ │ ├── Prefer pure functions where possible (no side effects = easy to test)
44
+ │ ├── The test MUST reference production code that does NOT exist yet
45
+ │ │ (this guarantees failure — no need to execute to confirm)
46
+ │ ├── If the production code/function already exists:
47
+ │ │ └── Write a test for the NEW behavior that is NOT yet implemented
48
+ │ └── GATE: Do NOT proceed to GREEN until the test is written
49
+
50
+ ├── 3. GREEN — Write the MINIMUM code to pass
51
+ │ ├── Implement ONLY what the failing test needs
52
+ │ ├── "Fake It" is VALID here (hardcoded return values are OK)
53
+ │ ├── EXECUTE the focused test → must PASS
54
+ │ │ ├── ✅ Passed → proceed to TRIANGULATE or REFACTOR
55
+ │ │ └── ❌ Failed → fix the implementation, NOT the test
56
+ │ └── GATE: Do NOT proceed until GREEN is confirmed by execution
57
+
58
+ ├── 4. TRIANGULATE (MANDATORY for most tasks)
59
+ │ ├── DEFAULT: triangulation is REQUIRED. You need a compelling reason to skip it.
60
+ │ ├── Add a second test case with DIFFERENT inputs/expected outputs
61
+ │ ├── EXECUTE tests → if "Fake It" breaks (the hardcode no longer works):
62
+ │ │ └── Generalize to real logic (this is the whole point)
63
+ │ ├── Repeat until ALL spec scenarios for this task are covered
64
+ │ ├── MINIMUM: at least 2 test cases per behavior (happy path + one edge case)
65
+ │ │ ├── One test with data that produces a NON-EMPTY/NON-TRIVIAL result
66
+ │ │ └── One test that exercises a DIFFERENT code path
67
+ │ ├── WATCH OUT for a GREEN that passes trivially:
68
+ │ │ ├── Passes because the component/element isn't rendered → NOT a real GREEN
69
+ │ │ ├── Passes because a loop iterates 0 times → NOT a real GREEN
70
+ │ │ ├── Passes because the setup never triggers the code path → NOT a real GREEN
71
+ │ │ └── A real GREEN means: production code RAN and produced the expected output
72
+ │ ├── Skip triangulation ONLY when ALL of these are true:
73
+ │ │ ├── The task is purely structural (config file, constant, type export)
74
+ │ │ ├── There is literally ONE possible output (no branching, no logic)
75
+ │ │ └── You note "Triangulation skipped: {reason}" in the evidence table
76
+ │ └── GATE: All spec scenarios for this task have tests before REFACTOR
77
+
78
+ ├── 5. REFACTOR — Improve without changing behavior
79
+ │ ├── Extract constants (eliminate magic numbers)
80
+ │ ├── Extract functions (reduce cyclomatic complexity)
81
+ │ ├── Improve naming, remove duplication, push toward pure functions
82
+ │ ├── Apply the Boy Scout Rule: leave code cleaner than you found it
83
+ │ ├── EXECUTE tests after EACH refactoring step → must STILL PASS
84
+ │ │ ├── ✅ Still passing → the refactoring is safe, continue
85
+ │ │ └── ❌ Failed → REVERT that step, try a smaller one
86
+ │ └── GATE: Tests green after EVERY refactoring change
87
+
88
+ ├── 6. Mark the task `[x]` in tasks.md
89
+ └── 7. Note any deviations or issues discovered
90
+ ```
91
+
92
+ ## Choosing Test Layer
93
+
94
+ ```
95
+ Determine the test layer by WHAT the task does:
96
+ ├── Pure logic, utility, calculation, data transformation
97
+ │ └── Unit test (always available when a test runner exists)
98
+
99
+ ├── Component rendering, user interaction, state changes
100
+ │ ├── IF integration tools available → Integration test
101
+ │ └── IF NOT → Unit test with mocks (degrade gracefully)
102
+
103
+ ├── Multi-component flow, API interaction, context/provider behavior
104
+ │ ├── IF integration tools available → Integration test
105
+ │ └── IF NOT → Unit test with mocks
106
+
107
+ ├── Critical business flow, full user journey, cross-page navigation
108
+ │ ├── IF E2E tools available → E2E test
109
+ │ ├── IF NOT but integration available → Integration test
110
+ │ └── IF neither → Unit test (degrade gracefully)
111
+
112
+ └── Default: Unit test (always the fallback)
113
+ ```
114
+
115
+ **Key rule**: use the HIGHEST available layer that fits the task, but NEVER skip
116
+ a task because a layer is unavailable — degrade to the next available layer.
117
+
118
+ ## Test Execution
119
+
120
+ Detect the test runner, in order:
121
+
122
+ ```
123
+ ├── `.sdd/config.json` → tdd.testCommand (explicit override, fastest)
124
+ └── Fallback: detect from package.json / pyproject.toml / go.mod / etc.
125
+
126
+ When executing tests during the cycle, run ONLY the relevant test file:
127
+ ├── JS/TS: {runner} {test-file} (e.g. npm test -- src/utils/tax.test.ts)
128
+ ├── Python: pytest {test-file}
129
+ ├── Go: go test ./{package}/... -run {TestName}
130
+ └── Adapt to the runner's CLI
131
+
132
+ Run a focused file, not the whole suite — it keeps the cycle FAST. The full
133
+ suite runs once at the end of the build phase (and again in veredicto).
134
+ ```
135
+
136
+ ## Pure Function Preference
137
+
138
+ When writing production code in GREEN/TRIANGULATE, prefer pure functions:
139
+
140
+ ```
141
+ ✅ PREFER (pure — easy to test):
142
+ function calculateDiscount(price: number, quantity: number): number {
143
+ return quantity >= 5 ? price * quantity * 0.1 : 0
144
+ }
145
+
146
+ ❌ AVOID (impure — hard to test):
147
+ function calculateDiscount(item: Item) {
148
+ globalState.lastDiscount = item.price * 0.1 // side effect
149
+ updateDOM() // side effect
150
+ return globalState.lastDiscount
151
+ }
152
+ ```
153
+
154
+ Pure functions are deterministic (same input → same output), have no side
155
+ effects, and are trivially testable. TDD naturally pushes you toward them —
156
+ embrace it, but don't force it where it doesn't fit (e.g. stateful components).
157
+
158
+ ## Approval Testing (for refactoring existing code)
159
+
160
+ When a task REFACTORS existing code (not writing new behavior):
161
+
162
+ ```
163
+ BEFORE touching production code:
164
+ ├── 1. Identify the existing behavior to preserve
165
+ ├── 2. Write "approval tests" that capture the current behavior:
166
+ │ ├── Call the function with known inputs
167
+ │ ├── Assert the CURRENT outputs (even if ugly)
168
+ │ └── These tests document what the code does NOW
169
+ ├── 3. Run approval tests → must PASS (they describe current reality)
170
+ ├── 4. NOW refactor the production code
171
+ ├── 5. Run approval tests again → must STILL PASS
172
+ │ ├── ✅ Passing → refactoring preserved behavior
173
+ │ └── ❌ Failing → refactoring broke something, revert
174
+ └── 6. If the spec says behavior should CHANGE:
175
+ ├── Update the approval test to the NEW expected behavior
176
+ ├── Run → test FAILS (RED — new behavior not implemented yet)
177
+ └── Implement the new behavior → GREEN
178
+ ```
179
+
180
+ ## TDD Cycle Evidence (MANDATORY output)
181
+
182
+ When Strict TDD Mode is active, the build phase MUST produce a **TDD Cycle
183
+ Evidence** table. Write it to `.sdd/<slug>/tdd-evidence.md` (create the file on
184
+ the first batch; append rows on later batches — never overwrite prior batches'
185
+ rows) AND include it in your return envelope so the veredicto phase can audit it.
186
+
187
+ ```markdown
188
+ ### TDD Cycle Evidence
189
+ | Task | Test File | Layer | Safety Net | RED | GREEN | TRIANGULATE | REFACTOR |
190
+ |------|-----------|-------|------------|-----|-------|-------------|----------|
191
+ | T001 | `path/test.ext` | Unit | ✅ 5/5 | ✅ Written | ✅ Passed | ✅ 3 cases | ✅ Clean |
192
+ | T002 | `path/test.ext` | Integration | N/A (new) | ✅ Written | ✅ Passed | ➖ Single | ✅ Clean |
193
+ | T003 | `path/test.ext` | Unit | ✅ 2/2 | ✅ Written | ✅ Passed | ✅ 2 cases | ➖ None needed |
194
+
195
+ ### Test Summary
196
+ - **Total tests written**: {N}
197
+ - **Total tests passing**: {N}
198
+ - **Layers used**: Unit ({N}), Integration ({N}), E2E ({N})
199
+ - **Approval tests** (refactoring): {N} or "None — no refactoring tasks"
200
+ - **Pure functions created**: {N}
201
+ ```
202
+
203
+ **Column definitions**:
204
+ - **Safety Net**: pre-existing tests run before modifying files. "N/A (new)" for new files.
205
+ - **RED**: test written first, referencing code that doesn't exist yet. Always "✅ Written".
206
+ - **GREEN**: tests executed and passing after minimal implementation. Must reflect an execution.
207
+ - **TRIANGULATE**: extra cases added to force real logic. "➖ Single" if the spec has one scenario.
208
+ - **REFACTOR**: code improved with tests still green. "➖ None needed" if already clean.
209
+
210
+ A build that omits this table when Strict TDD is active will be sent back as
211
+ `corregir` by veredicto — the table is the contract.
212
+
213
+ ## Assertion Quality Rules (MANDATORY)
214
+
215
+ **Every assertion must verify REAL behavior.** A test that passes without
216
+ exercising production logic is worse than no test — it gives false confidence.
217
+
218
+ ### Banned Assertion Patterns (NEVER write these)
219
+
220
+ ```
221
+ # TRIVIAL ASSERTIONS — the test proves nothing
222
+ expect(true).toBe(true) # ❌ Tautology
223
+ expect(1).toBe(1) # ❌ Tautology — no production code involved
224
+ assert True # ❌ Always passes
225
+
226
+ # EMPTY COLLECTION ASSERTIONS without setup context
227
+ expect(result).toEqual([]) # ❌ ONLY valid if you set up conditions for empty
228
+ expect(result).toHaveLength(0) # ❌ Why is it empty? Did production code run?
229
+ assert result == [] # ❌ Prove the emptiness comes from real logic
230
+
231
+ # TYPE-ONLY ASSERTIONS — proves existence, not behavior
232
+ expect(result).toBeDefined() # ❌ Alone is useless — WHAT is the value?
233
+ expect(result).not.toBeNull() # ❌ Alone is useless — assert the actual value
234
+ assert result is not None # ❌ Alone — assert what result actually IS
235
+
236
+ # GHOST LOOP — assertion inside a loop that iterates 0 times
237
+ const items = screen.queryAllByTestId("item"); // returns []
238
+ for (const item of items) {
239
+ expect(item).toHaveTextContent("value"); # ❌ NEVER EXECUTES — dead code
240
+ }
241
+ # FIX: assert the collection is non-empty FIRST, or set up data so it IS non-empty:
242
+ expect(items).toHaveLength(3); # ✅ Proves items exist
243
+ for (const item of items) { ... } # ✅ Now the loop actually runs
244
+ ```
245
+
246
+ ### What Makes a REAL Assertion
247
+
248
+ Every assertion must satisfy ALL of these:
249
+ 1. **Calls production code** — invokes a function, method, or component from the implementation.
250
+ 2. **Asserts a specific output** — compares against a concrete value derived from the spec.
251
+ 3. **Would FAIL if the production code were wrong** — change the logic and THIS test breaks.
252
+
253
+ ```
254
+ # ✅ REAL assertions — production code determines the result
255
+ expect(calculateDiscount(100, 10)).toBe(10)
256
+ expect(screen.getByText('Welcome, John')).toBeInTheDocument()
257
+ assert response.status_code == 403
258
+ expect(result).toHaveLength(3) # AND you set up exactly 3 items
259
+ ```
260
+
261
+ ### Empty Collection Rule
262
+
263
+ `expect(result).toEqual([])` / `assert len(result) == 0` is ONLY valid when:
264
+ 1. You set up a precondition that SHOULD produce an empty result.
265
+ 2. The production code actually ran and filtered/processed data to arrive at empty.
266
+ 3. A companion test with different setup produces a NON-EMPTY result (triangulation).
267
+
268
+ If you cannot explain WHY the result is empty from the setup → the assertion is trivial.
269
+
270
+ ### Smoke Test Rule
271
+
272
+ ```
273
+ # ❌ SMOKE TEST ONLY — proves nothing about behavior
274
+ render(<MyComponent data={mockData} />);
275
+ expect(screen.getByTestId("wrapper")).toBeInTheDocument();
276
+
277
+ # ✅ BEHAVIORAL TEST — proves what the component DOES with the data
278
+ render(<MyComponent data={mockData} />);
279
+ expect(screen.getByText("Expected Title")).toBeInTheDocument();
280
+ expect(screen.getByRole("button")).toHaveTextContent("Submit");
281
+ ```
282
+
283
+ "Renders without crash" is a smoke test. It does NOT count toward TDD coverage;
284
+ if you need one, it must be accompanied by real behavioral assertions.
285
+
286
+ ### Mock Hygiene Rules
287
+
288
+ **If you need more mocks than assertions, you are testing at the WRONG level.**
289
+
290
+ ```
291
+ ├── ≤ 3 mocks for a test file → ✅ Healthy — focused test
292
+ ├── 4–6 mocks → ⚠️ Consider extracting logic to a pure function
293
+ └── 7+ mocks → ❌ STOP — wrong layer
294
+ ├── Extract the logic to a PURE FUNCTION and test it without mocks, OR
295
+ └── Move the test to the integration/E2E layer where real deps exist
296
+ ```
297
+
298
+ **Extract-Before-Mock Rule**: if the behavior is a data transformation,
299
+ mapping, filtering, or conditional logic, EXTRACT it to a pure function FIRST,
300
+ then test the pure function directly — no mocks needed.
301
+
302
+ ### Implementation Detail Coupling Rule
303
+
304
+ Tests must assert **behavior visible to the user**, not internal details:
305
+
306
+ ```
307
+ # ❌ COUPLED — breaks on any style/internal refactor
308
+ expect(element.className).toContain("text-xs");
309
+ expect(mockService.mock.calls.length).toBe(3);
310
+ expect(component.state.isLoading).toBe(true);
311
+
312
+ # ✅ BEHAVIORAL — survives refactors, tests what users see
313
+ expect(screen.getByText("Error: Payment failed")).toBeInTheDocument();
314
+ expect(screen.getByRole("alert")).toHaveTextContent("Risk:");
315
+ expect(screen.getByRole("button")).toBeDisabled();
316
+ ```
317
+
318
+ **CSS class assertions are NEVER valid test assertions.** Verify the semantic
319
+ outcome (role, visible text, disabled state) or use a visual-regression/E2E
320
+ screenshot — never assert Tailwind/CSS class names.
321
+
322
+ ## Rules (Strict TDD specific)
323
+
324
+ - NEVER write production code before its test — this is the ONE rule that cannot be broken.
325
+ - NEVER skip the GREEN execution gate — you MUST run the test and confirm it passes.
326
+ - NEVER skip triangulation when the spec defines multiple scenarios.
327
+ - NEVER write trivial assertions (see Banned Patterns) — they are WORSE than no test.
328
+ - ALWAYS verify every assertion CALLS production code and asserts a SPECIFIC value.
329
+ - ALWAYS run the Safety Net before modifying existing files.
330
+ - ALWAYS write the TDD Cycle Evidence table — veredicto checks it.
331
+ - If a test-runner execution fails for infrastructure reasons (not a test failure), report it as "Blocked" and continue to the next task.
332
+ - For refactoring tasks, ALWAYS write approval tests before touching code.
333
+ - Run ONLY the relevant test file during the cycle, not the full suite.
File without changes
File without changes