ADR-1703 Phase 7 / epic #1702 closeout. The mechanical teardown is already complete across phases 1-6 (regex scanner retired P3, ratchet deleted P4, allowlist portability-usage gone, windows-portability-ok comments swept, every DEFECT.WINDOWS-* predicate rewritten per-phase). This phase delivers the two remaining ADR-mandated closeout items: - docs/contributing/adding-a-portability-rule.md: the forward architecture recipe (Diátaxis Explanation) — the five seams (rule / portability-vocab / platform-guard / disable-ban / ci-test-scope), the zero-escape-hatch contract, the shipped-rule catalog, and the step-by-step checklist for adding a new local/* portability rule. - docs/adr/1703: Status Proposed -> Accepted (all seven phases shipped); a Phase 7 as-built note recording the two deviations from the Phase 0 catalog — Phase 6's rename-only scope decision (#1740) and the codex-review precision tightening on require-fs-op-fallback. - docs/contributing/cross-platform-portability-rules.md: cross-link to the new guide from the rule reference. No code, no test, no runtime change. Epic #1702 Phase 6 box checked; Phase 7 box + epic closure to follow at PR merge. Closes #1744 Co-authored-by: review-bot <review-bot@gsd>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
# ADR-1703: Cross-platform portability enforcement as AST ESLint rules
|
||||
|
||||
- **Status:** Proposed
|
||||
- **Date:** 2026-06-25
|
||||
- **Status:** Accepted
|
||||
- **Date:** 2026-06-25 (Phase 0); **Accepted 2026-06-26** (Phase 7 closeout — all phases shipped)
|
||||
- **Issue:** [#1703](https://github.com/open-gsd/gsd-core/issues/1703) — Phase 0 of epic [#1702](https://github.com/open-gsd/gsd-core/issues/1702)
|
||||
- **Supersedes:** the regex-based `scripts/lint-windows-test-portability.cjs`, the
|
||||
`tests/windows-test-parity-guard.test.cjs` named-set ratchet (G1–G6), the
|
||||
@@ -186,6 +186,32 @@ Each implementation phase runs the full engineering directive (rubber-duck → l
|
||||
→ qa-test-architect → strict TDD via `RuleTester` → codex adversarial → Diátaxis → rebase+PR)
|
||||
and is its own approved child issue + PR under epic #1702.
|
||||
|
||||
## Phase 7 — as-built / acceptance (2026-06-26)
|
||||
|
||||
All seven phases shipped; the architecture is exercised in production and accepted. Two
|
||||
as-built deviations from the Phase 0 catalog, both within this ADR's precision discipline:
|
||||
|
||||
- **Phase 6 scope — `require-fs-op-fallback` narrowed to rename.** The catalog row named
|
||||
`DEFECT.WINDOWS-FS-OPS` for "`src/**/*.cts`, build/install". The defect's own `.fix-forward`
|
||||
defines the cure as *"catch EPERM/EBUSY/EACCES, fall back to copy + unlink with retry"* — so
|
||||
`copyFile`/`unlink` are the **fallback primitives**, not separate defect sites, and flagging
|
||||
them would flag the cure (`unlink` also has ~30 intentional best-effort cleanup sites that would
|
||||
be a FP minefield). v1 recognition is therefore `fs.rename`/`fs.renameSync` only, with the
|
||||
`RENAME_RETRY_ERRNOS` retry loop as the recognized compliant shape; `copyFile`/`unlink`
|
||||
transient-lock sub-classes are documented for a possible follow-up. The ADR-mandated glob
|
||||
expansion to `bin/install.js` + `scripts/build-hooks.js` (L124-126) landed as specified.
|
||||
Documented on [#1740](https://github.com/open-gsd/gsd-core/issues/1740).
|
||||
|
||||
- **Phase 6 precision tightening (codex review).** The rule's compliance shape was tightened after
|
||||
an adversarial gpt-5.5 review: a catch must BOTH reference a transient errno AND carry a retry
|
||||
signal (a loop `continue` backedge or a `return <call>` delegation — NOT a bare rethrow), and
|
||||
only the **nearest catching** try/catch counts (an outer errno-catch is unreachable once an inner
|
||||
catch intercepts). This enforces the defect's *"never silently swallow"* + cure-is-retry clauses
|
||||
honestly. See [`eslint-rules/require-fs-op-fallback.cjs`](../../eslint-rules/require-fs-op-fallback.cjs).
|
||||
|
||||
The forward "how to add a portability rule" recipe delivered by this phase lives at
|
||||
[`docs/contributing/adding-a-portability-rule.md`](../contributing/adding-a-portability-rule.md).
|
||||
|
||||
## Alternatives considered
|
||||
|
||||
1. **Keep extending the regex lint.** Rejected — the adversarial review proved it is
|
||||
|
||||
Reference in New Issue
Block a user