Skip to content

Commit 6ab44fd

Browse files
feat(skills/update-stack): block on undeclared drift vs upstream (#3760)
* feat(skills/update-stack): block on undeclared drift vs upstream Add gate 3ter to Phase 1: after /verify passes, diff each stack-module non-test file against devkit-node/master. Any file that diverges AND is not declared in DOWNSTREAM_PATCHES.md causes exit 1 with a clear fix message. Missing ledger = no declared divergences allowed. Prevents trawl-style silent drift (3 arch violations + 9 promote-up candidates found 2026-05-30 after weeks of unchecked accumulation). Closes #3759 — plan 2026-05-30-trawl-devkit-perfect-alignment.md (E.2) * fix(skills/update-stack): use HEAD blob + quoted path match in drift gate - Replace `git hash-object "$f"` with `git rev-parse HEAD:"$f"` — compares committed blobs rather than working-tree bytes (CRLF-safe, no false drift from uncommitted changes post-merge) - Replace `grep -qF "$f"` with `grep -qF "'$f'"` — matches the single-quoted token in DOWNSTREAM_PATCHES.md to prevent substring false-positives - Reword rules: remove misleading note about config/defaults auto-skip (those paths are simply not in the scanned directories), clarify that downstream-only files are never scanned Per Copilot review on #3760 * fix(skills/update-stack): add billing to stack module list + broaden test exclusion - Add `billing` to stack module declaration (it exists in devkit/Node: modules/billing/) — gate and header were inconsistent - Update conflict resolution table accordingly - Broaden test-file exclusion: add /__tests__/ directory pattern and extend extensions to (js|jsx|ts|tsx) for consistency Per CodeRabbit review on #3760
1 parent 0a9db27 commit 6ab44fd

1 file changed

Lines changed: 36 additions & 2 deletions

File tree

.claude/skills/update-stack/SKILL.md

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Two-phase workflow. Phase 1 brings the stack down ISO. Phase 2 aligns the projec
1717

1818
**Goal: stack modules and lib exit this phase identical to upstream. Zero downstream logic in them.**
1919

20-
Stack modules: `home`, `auth`, `users`, `tasks`, `uploads` — Stack core: `lib/` (existing files), `config/defaults/` (stack-owned files only)
20+
Stack modules: `home`, `auth`, `users`, `tasks`, `uploads`, `billing` — Stack core: `lib/` (existing files), `config/defaults/` (stack-owned files only)
2121

2222
### 1. Setup remote + merge
2323

@@ -31,7 +31,7 @@ git merge devkit-node/master
3131

3232
| File | Rule |
3333
|------|------|
34-
| Stack module (`modules/home\|auth\|users\|tasks\|uploads`) | `git checkout --theirs <file>` |
34+
| Stack module (`modules/home\|auth\|users\|tasks\|uploads\|billing`) | `git checkout --theirs <file>` |
3535
| `lib/<existing-file>` | `git checkout --theirs <file>` (existing stack framework files — always ISO) |
3636
| `config/defaults/development.js`, `production.js`, etc. | `git checkout --theirs <file>` (stack-owned defaults) |
3737
| `package-lock.json` | `git checkout --theirs package-lock.json` — regenerate after `package.json` is resolved |
@@ -88,6 +88,40 @@ BODY
8888

8989
Proceed to Phase 2 and track the upstream fix separately — do not block downstream alignment on it.
9090

91+
### 3ter. Block on undeclared drift
92+
93+
After `/verify` passes, run a final diff sweep before starting Phase 2. Any stack file that diverges from upstream **and** is not declared in `DOWNSTREAM_PATCHES.md` blocks the flow.
94+
95+
```bash
96+
git fetch devkit-node master --quiet
97+
98+
drift_found=0
99+
while IFS= read -r f; do
100+
upstream_blob=$(git ls-tree devkit-node/master -- "$f" 2>/dev/null | awk '{print $3}')
101+
[ -z "$upstream_blob" ] && continue # downstream-only file — skip
102+
local_blob=$(git rev-parse "HEAD:$f" 2>/dev/null)
103+
if [ "$upstream_blob" != "$local_blob" ]; then
104+
if ! grep -qF "'$f'" DOWNSTREAM_PATCHES.md 2>/dev/null; then
105+
echo "BLOCK: undeclared drift on stack file: $f"
106+
echo " Fix A — revert to upstream: git checkout devkit-node/master -- $f"
107+
echo " Fix B — declare it: add '$f' + rationale to DOWNSTREAM_PATCHES.md"
108+
drift_found=1
109+
fi
110+
fi
111+
done < <(git ls-files modules/home modules/auth modules/users modules/tasks modules/uploads modules/billing lib config/defaults 2>/dev/null \
112+
| grep -vE "/(tests|__tests__)/" | grep -vE "\.(test|spec)\.(js|jsx|ts|tsx)$")
113+
114+
[ "$drift_found" -eq 1 ] && exit 1
115+
echo "3ter: no undeclared drift — OK"
116+
```
117+
118+
**Rules:**
119+
- Missing `DOWNSTREAM_PATCHES.md` = no declared divergences allowed (treat as empty).
120+
- Declare diverging paths in `DOWNSTREAM_PATCHES.md` as `'path/to/file'` (single-quoted) — the gate matches on the quoted token to avoid substring collisions.
121+
- Downstream-only files (new modules, helpers, lib additions) are not scanned — the sweep only covers the stack directories listed above.
122+
- This gate runs **after** `/verify` (never blocks on transient verify failures) and **before** Phase 2 (failure is recoverable — no merge commit yet).
123+
- Ref: plan `2026-05-30-trawl-devkit-perfect-alignment.md` Tasks E.1 + E.2.
124+
91125
---
92126

93127
## Phase 2 — Project alignment

0 commit comments

Comments
 (0)