test-conformance's macos-latest leg (Phase 2, #4591) has been running the same 546-file, Windows-oriented conformance-tier list as windows-latest -- built from signals like windows-shell-token/windows-env-var that have nothing to do with macOS. Issue #4593 asked for macOS coverage sized to its own evidence-backed surface (zsh dispatch, case-sensitivity, darwin- specific behavior) instead. Issue #4593 was filed before Phase 5 (#4603) existed and referenced updating test-full's macOS legs -- that job is gone. Corrected the issue's body before any code was touched: the "shrink from full replay" half of the original ask was already done by Phase 5; what remained was narrowing the still-Windows-oriented tier macOS was inheriting. Two design assumptions were measured and rejected before accepting a design (documented in docs/adr/4593-macos-conformance-tier-architecture.md): - Reusing the general tier's signals minus its 3 Windows-specific categories barely narrows anything (546 -> 424, 78% retained) -- most files match multiple signals and only need one to survive exclusion. - A standalone CRLF/autocrlf signal, despite the issue naming "CRLF-checkout behavior": even narrowed to /\bCRLF\b|autocrlf/i it hit 143/930 files. Root cause: CRLF is primarily a Windows checkout concern in this codebase (ADR-1703 files it under DEFECT.WINDOWS-TEST- PORTABILITY), so the signal was really re-selecting Windows-relevant files already covered by the general tier, not narrowing macOS specifically. Built 5 new, genuinely macOS-specific signals instead: darwin-literal (darwin alone, not the general tier's win32-OR-darwin), zsh-dispatch, case-sensitivity, plus chmod-mode-bit and symlink-keyword reused verbatim from the general tier (genuinely Unix-relevant, not Windows-motivated). Measured against the real tree: 196 of 930 eligible unit-suite files (21%), versus the general tier's 546 (59%) -- a real, evidence-backed narrowing. scripts/gen-platform-conformance-tier.cjs gains classifyMacosContent/ classifyMacosTree/renderMacosGeneratedFile and a --target windows (default, unchanged)/--target macos CLI flag, so the same generator produces two independent, gated outputs rather than needing a second script. New committed output: scripts/lib/macos-conformance-tier. generated.cjs. .github/workflows/test.yml's test-conformance job: only the macos-latest leg's file-list source changes; windows-latest is byte-for-byte untouched. New shipped-file ripples handled proactively (19 install-tree fixtures regenerated, bin/install.js registered). An isolated code-review pass found one real defect: the ADR's per- category count table had drifted by 1 (zsh-dispatch, case-sensitivity) because the new test file's own fixture strings joined the tree it classifies after the table was authored -- fixed, with the union total (196, what CI actually gates on) confirmed unaffected. An isolated security-review pass found no qualifying findings. The ADR also records an explicit requirement for any future widening proposal: check whether the motivating regression is already covered by Phase 1's no-rendered-text-length-assert lint rule (#4590) before re-proposing full macOS/Linux parity, since that is exactly what #4421's root cause was (a rendered-text-length assertion, not a real behavioral divergence). Co-authored-by: sim <sim@local> Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
14
.github/workflows/test.yml
vendored
14
.github/workflows/test.yml
vendored
@@ -703,10 +703,20 @@ jobs:
|
||||
# scripts can `require()` it directly) — run-tests.cjs --files-from
|
||||
# expects a plain newline-delimited text file, so this step bridges
|
||||
# the two, one path per line, matching the existing scoped-lane
|
||||
# convention (.ci-selected-tests.txt).
|
||||
- name: Prepare conformance-tier test list
|
||||
# convention (.ci-selected-tests.txt). Windows keeps the general,
|
||||
# Windows-inclusive list.
|
||||
- name: Prepare conformance-tier test list (windows)
|
||||
if: matrix.os == 'windows-latest'
|
||||
run: node -e "require('./scripts/lib/platform-conformance-tier.generated.cjs').CONFORMANCE_TIER_FILES.forEach(f => console.log(f))" > .ci-conformance-tests.txt
|
||||
|
||||
# #4593: macOS reads a narrower, macOS-specific file list instead of the
|
||||
# shared/Windows-oriented one above — see
|
||||
# docs/adr/4593-macos-conformance-tier-architecture.md. Writes into the
|
||||
# same conventional filename so the run step below is unchanged.
|
||||
- name: Prepare conformance-tier test list (macos)
|
||||
if: matrix.os == 'macos-latest'
|
||||
run: node -e "require('./scripts/lib/macos-conformance-tier.generated.cjs').MACOS_CONFORMANCE_TIER_FILES.forEach(f => console.log(f))" > .ci-conformance-tests.txt
|
||||
|
||||
- name: Run platform-conformance-tier tests
|
||||
run: node scripts/run-tests.cjs --files-from .ci-conformance-tests.txt${{ matrix.shard && format(' --shard {0}', matrix.shard) || '' }}
|
||||
|
||||
|
||||
@@ -436,7 +436,7 @@ const GSD_CHANGESET_FILES = [
|
||||
'github-release-notes.cjs', 'lint.cjs', 'new.cjs',
|
||||
'README.md', // documentation only — not user-authored
|
||||
];
|
||||
const GSD_SCRIPTS_LIB_FILES = ['cli-exit.cjs', 'allowlist-ratchet.cjs', 'drift-scan.cjs', 'alias-drift-families.cjs', 'exit-code-registry.cjs', 'ndjson-reporter.cjs', 'ci-job-timing.cjs', 'shellcheck-fetch.cjs', 'npm-version-check-diagnosis.cjs', 'platform-conformance-tier.generated.cjs', 'suite-detection.cjs'];
|
||||
const GSD_SCRIPTS_LIB_FILES = ['cli-exit.cjs', 'allowlist-ratchet.cjs', 'drift-scan.cjs', 'alias-drift-families.cjs', 'exit-code-registry.cjs', 'ndjson-reporter.cjs', 'ci-job-timing.cjs', 'shellcheck-fetch.cjs', 'npm-version-check-diagnosis.cjs', 'platform-conformance-tier.generated.cjs', 'suite-detection.cjs', 'macos-conformance-tier.generated.cjs'];
|
||||
|
||||
/**
|
||||
* Resolve a runtime's shared-hooks directory name from its descriptor.
|
||||
|
||||
144
docs/adr/4593-macos-conformance-tier-architecture.md
Normal file
144
docs/adr/4593-macos-conformance-tier-architecture.md
Normal file
@@ -0,0 +1,144 @@
|
||||
# ADR-4593: A macOS-specific conformance-tier classifier, separate from the Windows-oriented one
|
||||
|
||||
- **Status:** Accepted
|
||||
- **Date:** 2026-09-10
|
||||
- **Issue:** [#4593](https://github.com/open-gsd/gsd-core/issues/4593) — Phase 4 (final) of epic [#4589](https://github.com/open-gsd/gsd-core/issues/4589)
|
||||
- **Twin of:** [ADR-1703](./1703-portability-enforcement-architecture.md) (Windows portability enforcement architecture) — this ADR
|
||||
applies ADR-1703's evidence-first, static-classifier discipline to a second, macOS-specific surface,
|
||||
rather than reusing ADR-1703's Windows-oriented signal set unmodified.
|
||||
|
||||
## Context
|
||||
|
||||
`test-conformance`'s `macos-latest` CI leg (#4591, epic #4589 Phase 2) runs only the
|
||||
`platform-conformance-tier` file list — a content classifier over `tests/**/*.test.cjs` that flags
|
||||
files needing real-OS coverage, replacing a full-suite replay. That list's signal set
|
||||
(`scripts/gen-platform-conformance-tier.cjs`'s `CATEGORIES`) was built for Windows: `windows-shell-token`,
|
||||
`windows-env-var`, `hardcoded-path-vs-path-call`, etc. `macos-latest` today runs the identical
|
||||
546-file list, which is Windows-oriented, not evidence-backed for macOS specifically.
|
||||
|
||||
#4593 was originally filed against `test-full`'s macOS legs, a job Phase 5 (#4603) has since
|
||||
deleted; the issue was corrected before design work started to target `test-conformance`'s
|
||||
`macos-latest` leg instead — the "shrink from full replay" half of the original ask was already
|
||||
done by Phase 2.
|
||||
|
||||
Naively narrowing the general tier to macOS by simply dropping its three Windows-specific
|
||||
categories (`windows-shell-token`, `windows-env-var`, `hardcoded-path-vs-path-call`) barely
|
||||
narrows anything: measured, 546 -> 424 files (78% retained), because most files match multiple
|
||||
signals simultaneously and only need one surviving signal to stay in the tier. That is nowhere
|
||||
near the narrow, evidence-backed surface the issue asks for.
|
||||
|
||||
## Decision
|
||||
|
||||
Build a second, macOS-specific classifier (`classifyMacosContent` / `MACOS_CATEGORIES`) in the
|
||||
same generator file, matching the issue's own named surface (zsh dispatch, case-sensitivity,
|
||||
darwin-specific behavior) plus two categories reused verbatim from the general tier that are
|
||||
genuinely Unix-relevant rather than Windows-motivated:
|
||||
|
||||
| Category | Test | Rationale | Files matched (of 930 eligible) |
|
||||
|---|---|---|---|
|
||||
| `darwin-literal` | `/\bdarwin\b/` (darwin alone, not the general tier's `win32-darwin-literal` OR) | The general tier's combined `win32\|darwin` category can't distinguish which branch fired; a file mentioning only `win32` says nothing about macOS. | 8 |
|
||||
| `zsh-dispatch` | `/\bzsh\b/i` | Directly names the issue's own "zsh shell dispatch" surface. | 14 |
|
||||
| `case-sensitivity` | `/case.?insensitiv\|case.?sensitiv/i` | Directly names the issue's own "case-sensitivity" surface (macOS's default case-insensitive-but-preserving filesystem). | 74 |
|
||||
| `chmod-mode-bit` | reused verbatim from the general tier's `CATEGORIES` | Unix permission-bit semantics — genuinely macOS/Linux-relevant, not a Windows category (Windows has no chmod). | 73 |
|
||||
| `symlink-keyword` | reused verbatim from the general tier's `CATEGORIES` | Symlink handling differs materially on macOS (case-insensitive-but-preserving FS, different default symlink permissions) — not Windows-motivated the way `windows-shell-token` etc. are. | 86 |
|
||||
|
||||
Applied to the real `tests/` unit-suite tree (930 files eligible under the same `suiteOf(f) === null`
|
||||
gate the general tier uses), the union is **196 files** (21% of eligible files, vs. the general
|
||||
tier's 546/930, 59%) — a materially narrower, macOS-evidence-backed tier. The per-category counts
|
||||
above include `tests/platform-conformance-tier.test.cjs`'s own new fixture strings for
|
||||
`zsh-dispatch`/`case-sensitivity` (e.g. `"shell: 'zsh {0}'"`) — self-referential by one file each,
|
||||
since this test file lives in the same tree it classifies. Caught by an isolated code-review pass
|
||||
comparing this table against a fresh live count; the union total was unaffected (that file was
|
||||
already in the tier via an unrelated signal).
|
||||
|
||||
### Rejected: a standalone CRLF/`autocrlf` signal
|
||||
|
||||
The issue's own surface description names "CRLF-checkout behavior" as part of macOS's risk. This
|
||||
was measured and rejected as a standalone macOS signal:
|
||||
|
||||
- The obvious first attempt, a literal `/\r\n/` match, hit 197/952 files (21% of all test files) —
|
||||
far too broad, because it matches routine defensive newline-normalization code
|
||||
(`.replace(/\r\n/g, '\n')`) present throughout the suite for unrelated reasons, not files
|
||||
specifically at CRLF-checkout risk.
|
||||
- Narrowing to the actual named terms, `/\bCRLF\b|autocrlf/i`, still hit 143 files — still too
|
||||
broad to be a precise macOS-only signal.
|
||||
- Root cause: in this codebase, CRLF is primarily a **Windows** checkout concern — ADR-1703 files
|
||||
its `no-crlf-fragile-split` rule under `DEFECT.WINDOWS-TEST-PORTABILITY`, not a macOS defect
|
||||
class. A CRLF-keyword signal was therefore pulling in files already covered by the general,
|
||||
Windows-oriented tier, not narrowing macOS coverage specifically.
|
||||
|
||||
The issue's "CRLF-checkout" framing is treated as "this is one of the risk categories macOS needs
|
||||
coverage for" — already satisfied, for files that actually need it, by the general tier — not "this
|
||||
is a macOS-exclusive signal to build."
|
||||
|
||||
### Implementation
|
||||
|
||||
- `scripts/gen-platform-conformance-tier.cjs` gains `MACOS_CATEGORIES`, `classifyMacosContent`,
|
||||
`classifyMacosTree`, and `renderMacosGeneratedFile`, mirroring the general tier's
|
||||
`CATEGORIES`/`classifyContent`/`classifyTree`/`renderGeneratedFile` exactly (same `suiteOf(f)
|
||||
=== null` eligibility gate — see ADR-1703's sibling doc-comment in that file for why suite-tagged
|
||||
files are excluded entirely rather than merely deprioritized). A new `--target windows`
|
||||
(default, unchanged) / `--target macos` CLI flag selects which of the two independent generated
|
||||
outputs a given `--check`/`--write`/print invocation targets, so `package.json`'s
|
||||
`lint:generated-sync`/`regen:derived` chains invoke the same script twice rather than needing a
|
||||
second script file.
|
||||
- New committed output `scripts/lib/macos-conformance-tier.generated.cjs`, exporting
|
||||
`MACOS_CONFORMANCE_TIER_FILES` — same generated-file convention (one array entry per line,
|
||||
sorted, `GENERATED FILE` header banner) as `platform-conformance-tier.generated.cjs`. Gated by
|
||||
the same `lint:generated-sync --check` fail-safe as the general tier — no new fail-safe mechanism
|
||||
needed; this is a second instance of an already-proven pattern.
|
||||
- `.github/workflows/test.yml`'s `test-conformance` job: the `macos-latest` leg's "prepare
|
||||
conformance-tier test list" step reads `MACOS_CONFORMANCE_TIER_FILES` instead of the shared
|
||||
`CONFORMANCE_TIER_FILES`, writing into the same conventional `.ci-conformance-tests.txt`
|
||||
filename so the downstream `run-tests.cjs --files-from` step is unchanged. The `windows-latest`
|
||||
legs, their shard count, and everything else about the job are untouched — they keep using the
|
||||
general, Windows-inclusive tier.
|
||||
|
||||
## Explicit requirement for future widening proposals
|
||||
|
||||
Per issue #4593's "Done when": **before any future proposal to widen macOS coverage beyond this
|
||||
196-file tier, check whether the motivating regression class is already covered by Phase 1's
|
||||
`no-rendered-text-length-assert` ESLint rule (#4590, cataloged in ADR-1703)** — an author-time,
|
||||
zero-escape-hatch rule that catches exactly the shape behind #4421 (a rendered-text-length
|
||||
assertion embedding an OS-derived path, e.g. `os.tmpdir()`, whose length differs between macOS's
|
||||
`/private/var/folders/…` prefix and Linux's shorter one). #4421's root cause was that
|
||||
static-assertion shape, not a real macOS behavioral divergence requiring dynamic real-OS
|
||||
execution to catch. A future explorer proposing full macOS/Linux parity coverage should confirm
|
||||
new evidence of a *behavioral* divergence this static classifier and `no-rendered-text-length-assert`
|
||||
both miss, rather than re-proposing parity on the strength of #4421 alone — #4421 is already
|
||||
covered.
|
||||
|
||||
## Consequences
|
||||
|
||||
**Positive:** `macos-latest` now runs a narrower, macOS-evidence-backed 196-file tier (down from
|
||||
the shared 546-file Windows-oriented list) — a real reduction (~64%) in real-OS macOS CI minutes
|
||||
for files with no macOS-specific signal, without dropping coverage for files that do carry one.
|
||||
Same generator, same fail-safe convention, same install/build ripple discipline as the general
|
||||
tier — no new mechanism class.
|
||||
|
||||
**Cost / risk:** a second static classifier is still subject to the same disclosed limit as the
|
||||
general tier (ADR-1703 / `gen-platform-conformance-tier.cjs`'s own header doc-comment): it is
|
||||
content-based, not a real per-file behavioral diff. Mitigated the same way — the most recent
|
||||
full-matrix `next` run was green on every file in this classification before it was built. The
|
||||
legacy full-matrix macOS job's actual safety-net window was much shorter than originally planned:
|
||||
Phase 2 (#4591) added it as a non-gating safety net intended for "one release cycle," but Phase 5
|
||||
(#4603) retired it roughly 4 hours later, the same day, after discovering it was purely additive to
|
||||
the new conformance job (10 OS-specific CI jobs per PR instead of the intended reduction) rather
|
||||
than a genuine transition period — see #4603 for the full accounting. `macos-latest`'s coverage
|
||||
here has not yet had an extended real-world safety-net window of its own; that is an accepted,
|
||||
disclosed risk of shipping Phase 4 promptly rather than waiting, consistent with this epic's general
|
||||
preference for fast, evidence-driven iteration over a long unmonitored parallel-running period.
|
||||
|
||||
## Alternatives considered
|
||||
|
||||
1. **Apply the general tier's signals minus the three Windows-specific categories.** Rejected —
|
||||
measured at 424/546 files (78% retained), nowhere near the narrow, macOS-evidence-backed
|
||||
surface the issue asks for; see "Context" above.
|
||||
2. **A standalone CRLF/`autocrlf` signal.** Rejected — see "Rejected: a standalone CRLF/`autocrlf`
|
||||
signal" above; both attempted regexes (197 and 143 files) were too broad and were really
|
||||
re-selecting Windows-relevant files already covered by the general tier.
|
||||
3. **A single, unified classifier covering both Windows and macOS signals, with per-OS filtering
|
||||
at CI-invocation time.** Rejected — would still need two independent signal sets internally to
|
||||
produce two independently-narrow lists, so it does not actually simplify anything over two
|
||||
sibling classifier functions in the same file; a single combined list reproduces the 78%-retained
|
||||
problem from alternative 1.
|
||||
@@ -268,6 +268,7 @@ These govern the system as it stands. Cite these.
|
||||
| [ADR-3660](3660-runtime-artifact-layout-module.md) | Runtime Artifact Layout Module owns per-runtime artifact placement | Accepted | [ADR-1239](1239-gsd-embeddable-orchestration-engine.md) |
|
||||
| [ADR-3806](3806-review-dispositions-ledger.md) | Review Dispositions Ledger canonizes where and how reviews-mode records incorporate/defer decisions in PLAN.md | Accepted | — |
|
||||
| [ADR-4139](4139-compact-content-seam.md) | The compact-content seam — shrink the eager window, never the guarantee | Accepted | — |
|
||||
| [ADR-4593](4593-macos-conformance-tier-architecture.md) | A macOS-specific conformance-tier classifier, separate from the Windows-oriented one | Accepted | — |
|
||||
|
||||
### Proposed
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@
|
||||
"gen:registry": "node scripts/gen-registry.cjs --write",
|
||||
"gen:install-tree": "node scripts/gen-install-tree-fixtures.cjs",
|
||||
"gen:section-manifest": "node scripts/gen-section-manifest.cjs --write",
|
||||
"regen:derived": "npm run build && npm run gen:registry && node scripts/gen-adr-index.cjs --write && node scripts/gen-features.cjs --write && node scripts/gen-capability-matrix.cjs --write && node scripts/gen-inventory-manifest.cjs --write && node scripts/gen-context-index.cjs --write && node scripts/gen-state-md-docs.cjs --write && npm run gen:section-manifest && node scripts/sync-manifest-versions.cjs && npm run gen:install-tree && node scripts/gen-scripts-cli-exit.cjs --write && node scripts/gen-hooks-cli-exit.cjs --write && node scripts/gen-exit-code-registry.cjs --write && node scripts/gen-exit-code-docs.cjs --write && node scripts/gen-platform-conformance-tier.cjs --write",
|
||||
"regen:derived": "npm run build && npm run gen:registry && node scripts/gen-adr-index.cjs --write && node scripts/gen-features.cjs --write && node scripts/gen-capability-matrix.cjs --write && node scripts/gen-inventory-manifest.cjs --write && node scripts/gen-context-index.cjs --write && node scripts/gen-state-md-docs.cjs --write && npm run gen:section-manifest && node scripts/sync-manifest-versions.cjs && npm run gen:install-tree && node scripts/gen-scripts-cli-exit.cjs --write && node scripts/gen-hooks-cli-exit.cjs --write && node scripts/gen-exit-code-registry.cjs --write && node scripts/gen-exit-code-docs.cjs --write && node scripts/gen-platform-conformance-tier.cjs --write && node scripts/gen-platform-conformance-tier.cjs --target macos --write",
|
||||
"validate:registry": "node scripts/validate-registry.cjs",
|
||||
"prepack": "npm run build:lib",
|
||||
"prepare": "npm run build:lib",
|
||||
@@ -132,7 +132,7 @@
|
||||
"lint:test-file-count": "node scripts/lint-test-file-count.cjs",
|
||||
"lint:pr-checks": "node scripts/lint-pr-check-project-dir.cjs",
|
||||
"lint:changeset": "node scripts/changeset/lint.cjs",
|
||||
"lint:generated-sync": "node scripts/gen-capability-registry.cjs --check && node scripts/gen-loop-host-contract.cjs --check && node scripts/gen-capability-matrix.cjs --check && node scripts/sync-manifest-versions.cjs --check && node scripts/gen-inventory-manifest.cjs --check && node scripts/generate-package-identity.cjs --check && node scripts/gen-plugin-skills.cjs --check && node scripts/gen-registry.cjs --check && node scripts/gen-adr-index.cjs --check && node scripts/gen-features.cjs --check && node scripts/check-glossary-refs.cjs --check && node scripts/lint-compiled-artifact-sync.cjs --check && node scripts/gen-context-index.cjs --check && node scripts/gen-section-manifest.cjs --check && node scripts/gen-health-docs.cjs --check && node scripts/gen-state-md-docs.cjs --check && node scripts/gen-scripts-cli-exit.cjs --check && node scripts/gen-hooks-cli-exit.cjs --check && node scripts/gen-exit-code-registry.cjs --check && node scripts/gen-exit-code-docs.cjs --check && node scripts/gen-platform-conformance-tier.cjs --check",
|
||||
"lint:generated-sync": "node scripts/gen-capability-registry.cjs --check && node scripts/gen-loop-host-contract.cjs --check && node scripts/gen-capability-matrix.cjs --check && node scripts/sync-manifest-versions.cjs --check && node scripts/gen-inventory-manifest.cjs --check && node scripts/generate-package-identity.cjs --check && node scripts/gen-plugin-skills.cjs --check && node scripts/gen-registry.cjs --check && node scripts/gen-adr-index.cjs --check && node scripts/gen-features.cjs --check && node scripts/check-glossary-refs.cjs --check && node scripts/lint-compiled-artifact-sync.cjs --check && node scripts/gen-context-index.cjs --check && node scripts/gen-section-manifest.cjs --check && node scripts/gen-health-docs.cjs --check && node scripts/gen-state-md-docs.cjs --check && node scripts/gen-scripts-cli-exit.cjs --check && node scripts/gen-hooks-cli-exit.cjs --check && node scripts/gen-exit-code-registry.cjs --check && node scripts/gen-exit-code-docs.cjs --check && node scripts/gen-platform-conformance-tier.cjs --check && node scripts/gen-platform-conformance-tier.cjs --target macos --check",
|
||||
"lint:docs": "node scripts/lint-docs-required.cjs",
|
||||
"lint:qa-smells": "node scripts/qa-smell-ratchet.cjs",
|
||||
"lint:legacy-name": "node scripts/lint-legacy-dir-name.cjs",
|
||||
|
||||
@@ -58,9 +58,19 @@
|
||||
* node scripts/gen-platform-conformance-tier.cjs # print summary to stdout
|
||||
* node scripts/gen-platform-conformance-tier.cjs --write # write the generated file
|
||||
* node scripts/gen-platform-conformance-tier.cjs --check # exit 1 if the committed file is stale
|
||||
* node scripts/gen-platform-conformance-tier.cjs --target macos ... # same three modes, macOS-specific list (#4593)
|
||||
* node scripts/gen-platform-conformance-tier.cjs --tests-dir <path> # override the tests/ root (tests only)
|
||||
* node scripts/gen-platform-conformance-tier.cjs --out <path> # override the generated-file path (tests only)
|
||||
*
|
||||
* `--target` selects which of the two independent generated outputs this
|
||||
* invocation targets: `windows` (default, the original #4591 behavior —
|
||||
* omitting the flag is unchanged) or `macos` (#4593's narrower, macOS-
|
||||
* specific list). Both write into the SAME committed-file conventions
|
||||
* (`scripts/lib/platform-conformance-tier.generated.cjs` /
|
||||
* `scripts/lib/macos-conformance-tier.generated.cjs`), so `package.json`'s
|
||||
* `lint:generated-sync`/`regen:derived` chains invoke this script twice, once
|
||||
* per target, rather than needing a second script file.
|
||||
*
|
||||
* `--tests-dir`/`--out` (or the TESTS_DIR/OUT_PATH env vars, flag takes
|
||||
* precedence) exist solely so tests/platform-conformance-tier.test.cjs can
|
||||
* point the CLI at a small temp fixture tree instead of this repo's real,
|
||||
@@ -77,10 +87,17 @@ const { suiteOf } = require('./lib/suite-detection.cjs');
|
||||
const ROOT = path.resolve(__dirname, '..');
|
||||
const DEFAULT_TESTS_DIR = path.join(ROOT, 'tests');
|
||||
const DEFAULT_OUT_PATH = path.join(ROOT, 'scripts', 'lib', 'platform-conformance-tier.generated.cjs');
|
||||
const DEFAULT_MACOS_OUT_PATH = path.join(ROOT, 'scripts', 'lib', 'macos-conformance-tier.generated.cjs');
|
||||
|
||||
const GENERATED_HEADER =
|
||||
'// GENERATED FILE — do not hand-edit. Run `node scripts/gen-platform-conformance-tier.cjs --write` to regenerate.\n';
|
||||
|
||||
const MACOS_GENERATED_HEADER =
|
||||
'// GENERATED FILE — do not hand-edit. Run `node scripts/gen-platform-conformance-tier.cjs --target macos --write` to regenerate.\n' +
|
||||
'// macOS-specific conformance tier (#4593), separate from and narrower than the general/\n' +
|
||||
'// Windows-oriented tier in platform-conformance-tier.generated.cjs — see\n' +
|
||||
'// docs/adr/4593-macos-conformance-tier-architecture.md for the full rationale.\n';
|
||||
|
||||
/**
|
||||
* Detection categories (#4591 design doc). Each entry's `test` receives the
|
||||
* raw file content string and returns true when that category's signal is
|
||||
@@ -158,6 +175,31 @@ const CATEGORIES = [
|
||||
// to 28 files, all verified to carry a genuine platform-conditional branch.
|
||||
const NOISY_FOR_SOURCE_REACHABILITY = new Set(['hardcoded-path-vs-path-call', 'symlink-keyword']);
|
||||
|
||||
/**
|
||||
* macOS-specific detection categories (#4593, design doc
|
||||
* .gsd/phase/chore-4593-macos-conformance-tier/40-design.md). Built new,
|
||||
* rather than reusing CATEGORIES above minus its Windows-specific entries,
|
||||
* because that naive exclusion barely narrows anything (measured: 546 -> 424
|
||||
* files, 78%) — most files match multiple general-tier signals simultaneously
|
||||
* and only need ONE surviving signal to stay in. `chmod-mode-bit` and
|
||||
* `symlink-keyword` ARE deliberately duplicated verbatim from CATEGORIES:
|
||||
* both are genuinely Unix-relevant (chmod bits and symlink semantics differ
|
||||
* materially on macOS), not Windows-motivated the way the rest of CATEGORIES
|
||||
* is. A standalone CRLF/`autocrlf` signal was considered and rejected: even
|
||||
* narrowed to `/\bCRLF\b|autocrlf/i` it still hit 143/930 files (15%) — CRLF
|
||||
* is primarily a Windows checkout concern in this codebase (ADR-1703's
|
||||
* `no-crlf-fragile-split` files it under DEFECT.WINDOWS-TEST-PORTABILITY),
|
||||
* so a CRLF signal pulls in Windows-relevant files already covered by the
|
||||
* general tier, not a macOS-narrowing one.
|
||||
*/
|
||||
const MACOS_CATEGORIES = [
|
||||
{ name: 'darwin-literal', test: (content) => /\bdarwin\b/.test(content) },
|
||||
{ name: 'zsh-dispatch', test: (content) => /\bzsh\b/i.test(content) },
|
||||
{ name: 'case-sensitivity', test: (content) => /case.?insensitiv|case.?sensitiv/i.test(content) },
|
||||
{ name: 'chmod-mode-bit', test: (content) => /chmodSync|chmod\(/.test(content) || /0o[0-7]{3,4}\b/.test(content) },
|
||||
{ name: 'symlink-keyword', test: (content) => /\bsymlink/i.test(content) },
|
||||
];
|
||||
|
||||
/**
|
||||
* Pure classifier: given a test file's raw string content, returns which
|
||||
* platform-conformance categories matched and whether the file needs real-OS
|
||||
@@ -175,6 +217,22 @@ function classifyContent(content) {
|
||||
return { needsRealOs: signals.length > 0, signals };
|
||||
}
|
||||
|
||||
/**
|
||||
* Pure classifier, macOS-specific signal set (#4593). Same shape as
|
||||
* classifyContent, against MACOS_CATEGORIES instead of CATEGORIES.
|
||||
*
|
||||
* @param {string} content
|
||||
* @returns {{needsRealOs: boolean, signals: string[]}}
|
||||
*/
|
||||
function classifyMacosContent(content) {
|
||||
const text = typeof content === 'string' ? content : '';
|
||||
const signals = [];
|
||||
for (const category of MACOS_CATEGORIES) {
|
||||
if (category.test(text)) signals.push(category.name);
|
||||
}
|
||||
return { needsRealOs: signals.length > 0, signals };
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively collect every `*.test.cjs` file beneath `dir`.
|
||||
* @param {string} dir
|
||||
@@ -227,6 +285,29 @@ function classifyTree(testsDir) {
|
||||
return { total: absoluteFiles.length, files: flagged };
|
||||
}
|
||||
|
||||
/**
|
||||
* Same walk/eligibility as classifyTree, classified with the macOS-specific
|
||||
* signal set (#4593).
|
||||
*
|
||||
* @param {string} testsDir
|
||||
* @returns {{ total: number, files: string[] }}
|
||||
*/
|
||||
function classifyMacosTree(testsDir) {
|
||||
const absoluteFiles = walkTestFiles(testsDir);
|
||||
const unitFiles = absoluteFiles.filter((absPath) => suiteOf(absPath) === null);
|
||||
const flagged = [];
|
||||
for (const absPath of unitFiles) {
|
||||
const content = fs.readFileSync(absPath, 'utf8');
|
||||
const { needsRealOs } = classifyMacosContent(content);
|
||||
if (needsRealOs) {
|
||||
const rel = path.relative(testsDir, absPath).replace(/\\/g, '/');
|
||||
flagged.push('tests/' + rel);
|
||||
}
|
||||
}
|
||||
flagged.sort();
|
||||
return { total: absoluteFiles.length, files: flagged };
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the generated `.cjs` module body — one array entry per line for a
|
||||
* readable diff, matching scripts/lib/portability-vocab.cjs's array-literal
|
||||
@@ -248,10 +329,43 @@ function renderGeneratedFile(files) {
|
||||
);
|
||||
}
|
||||
|
||||
/** Resolve the effective tests-dir / out-path from argv/env, flag beats env. */
|
||||
/**
|
||||
* Render scripts/lib/macos-conformance-tier.generated.cjs's module body,
|
||||
* mirroring renderGeneratedFile exactly against the macOS export name.
|
||||
*
|
||||
* @param {string[]} files - already sorted.
|
||||
* @returns {string}
|
||||
*/
|
||||
function renderMacosGeneratedFile(files) {
|
||||
const lines = files.map((f) => ` ${JSON.stringify(f)},`).join('\n');
|
||||
return (
|
||||
MACOS_GENERATED_HEADER +
|
||||
"'use strict';\n\n" +
|
||||
'module.exports = {\n' +
|
||||
' MACOS_CONFORMANCE_TIER_FILES: [\n' +
|
||||
(lines.length > 0 ? lines + '\n' : '') +
|
||||
' ],\n' +
|
||||
'};\n'
|
||||
);
|
||||
}
|
||||
|
||||
/** Resolve the effective target/tests-dir/out-path from argv/env, flag beats env. */
|
||||
function resolveOverrides(argv) {
|
||||
let target = 'windows';
|
||||
for (let i = 0; i < argv.length; i++) {
|
||||
if (argv[i] === '--target') {
|
||||
const value = argv[i + 1];
|
||||
if (value !== 'windows' && value !== 'macos') {
|
||||
throw new ExitError(1, 'gen-platform-conformance-tier: --target requires "windows" or "macos"');
|
||||
}
|
||||
target = value;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
const defaultOutPath = target === 'macos' ? DEFAULT_MACOS_OUT_PATH : DEFAULT_OUT_PATH;
|
||||
let testsDir = process.env.TESTS_DIR || DEFAULT_TESTS_DIR;
|
||||
let outPath = process.env.OUT_PATH || DEFAULT_OUT_PATH;
|
||||
let outPath = process.env.OUT_PATH || defaultOutPath;
|
||||
|
||||
for (let i = 0; i < argv.length; i++) {
|
||||
if (argv[i] === '--tests-dir') {
|
||||
@@ -271,19 +385,22 @@ function resolveOverrides(argv) {
|
||||
}
|
||||
}
|
||||
|
||||
return { testsDir: path.resolve(testsDir), outPath: path.resolve(outPath) };
|
||||
return { target, testsDir: path.resolve(testsDir), outPath: path.resolve(outPath) };
|
||||
}
|
||||
|
||||
function main() {
|
||||
const argv = process.argv.slice(2);
|
||||
const { testsDir, outPath } = resolveOverrides(argv);
|
||||
const { target, testsDir, outPath } = resolveOverrides(argv);
|
||||
const mode = argv.includes('--check') ? 'check' : argv.includes('--write') ? 'write' : 'print';
|
||||
|
||||
const { total, files } = classifyTree(testsDir);
|
||||
const isMacos = target === 'macos';
|
||||
const label = isMacos ? 'gen-platform-conformance-tier --target macos' : 'gen-platform-conformance-tier';
|
||||
const exportKey = isMacos ? 'MACOS_CONFORMANCE_TIER_FILES' : 'CONFORMANCE_TIER_FILES';
|
||||
const { total, files } = isMacos ? classifyMacosTree(testsDir) : classifyTree(testsDir);
|
||||
|
||||
if (mode === 'write') {
|
||||
fs.mkdirSync(path.dirname(outPath), { recursive: true });
|
||||
fs.writeFileSync(outPath, renderGeneratedFile(files));
|
||||
fs.writeFileSync(outPath, isMacos ? renderMacosGeneratedFile(files) : renderGeneratedFile(files));
|
||||
process.stdout.write(`Wrote ${outPath} (${files.length} conformance-tier file(s))\n`);
|
||||
return;
|
||||
}
|
||||
@@ -299,14 +416,12 @@ function main() {
|
||||
} catch (err) {
|
||||
throw new ExitError(
|
||||
1,
|
||||
`gen-platform-conformance-tier: could not load ${outPath} — run ` +
|
||||
'`node scripts/gen-platform-conformance-tier.cjs --write` first ' +
|
||||
`${label}: could not load ${outPath} — run ` +
|
||||
`\`node scripts/gen-platform-conformance-tier.cjs${isMacos ? ' --target macos' : ''} --write\` first ` +
|
||||
`(${err && err.message ? err.message : err})`,
|
||||
);
|
||||
}
|
||||
const committedFiles = Array.isArray(committed.CONFORMANCE_TIER_FILES)
|
||||
? committed.CONFORMANCE_TIER_FILES
|
||||
: [];
|
||||
const committedFiles = Array.isArray(committed[exportKey]) ? committed[exportKey] : [];
|
||||
const committedSet = new Set(committedFiles);
|
||||
const liveSet = new Set(files);
|
||||
|
||||
@@ -316,22 +431,20 @@ function main() {
|
||||
if (added.length > 0 || removed.length > 0) {
|
||||
process.stderr.write(
|
||||
`${path.relative(ROOT, outPath).replace(/\\/g, '/')} is stale. Run:\n` +
|
||||
' node scripts/gen-platform-conformance-tier.cjs --write\n\n',
|
||||
` node scripts/gen-platform-conformance-tier.cjs${isMacos ? ' --target macos' : ''} --write\n\n`,
|
||||
);
|
||||
for (const f of added) process.stderr.write(' + ' + f + '\n');
|
||||
for (const f of removed) process.stderr.write(' - ' + f + '\n');
|
||||
throw new ExitError(1);
|
||||
}
|
||||
|
||||
process.stdout.write(
|
||||
`ok gen-platform-conformance-tier: ${files.length} conformance-tier files, list matches\n`,
|
||||
);
|
||||
process.stdout.write(`ok ${label}: ${files.length} conformance-tier files, list matches\n`);
|
||||
return;
|
||||
}
|
||||
|
||||
// No flag: print a classification summary, write nothing.
|
||||
process.stdout.write(
|
||||
`gen-platform-conformance-tier: ${total} file(s) scanned, ` +
|
||||
`${label}: ${total} file(s) scanned, ` +
|
||||
`${files.length} need real OS, ${total - files.length} excluded (Linux-only conformance tier eligible)\n`,
|
||||
);
|
||||
}
|
||||
@@ -341,4 +454,15 @@ if (require.main === module) {
|
||||
runMain(main);
|
||||
}
|
||||
|
||||
module.exports = { classifyContent, CATEGORIES, NOISY_FOR_SOURCE_REACHABILITY, walkTestFiles, classifyTree, renderGeneratedFile };
|
||||
module.exports = {
|
||||
classifyContent,
|
||||
CATEGORIES,
|
||||
NOISY_FOR_SOURCE_REACHABILITY,
|
||||
walkTestFiles,
|
||||
classifyTree,
|
||||
renderGeneratedFile,
|
||||
classifyMacosContent,
|
||||
MACOS_CATEGORIES,
|
||||
classifyMacosTree,
|
||||
renderMacosGeneratedFile,
|
||||
};
|
||||
|
||||
206
scripts/lib/macos-conformance-tier.generated.cjs
Normal file
206
scripts/lib/macos-conformance-tier.generated.cjs
Normal file
@@ -0,0 +1,206 @@
|
||||
// GENERATED FILE — do not hand-edit. Run `node scripts/gen-platform-conformance-tier.cjs --target macos --write` to regenerate.
|
||||
// macOS-specific conformance tier (#4593), separate from and narrower than the general/
|
||||
// Windows-oriented tier in platform-conformance-tier.generated.cjs — see
|
||||
// docs/adr/4593-macos-conformance-tier-architecture.md for the full rationale.
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
MACOS_CONFORMANCE_TIER_FILES: [
|
||||
"tests/adr-index-gate.test.cjs",
|
||||
"tests/adr-parser.property.test.cjs",
|
||||
"tests/adr-parser.unit.test.cjs",
|
||||
"tests/agent-classification-parity.test.cjs",
|
||||
"tests/agent-install-check.test.cjs",
|
||||
"tests/agent-skills.test.cjs",
|
||||
"tests/api-coverage-gate-e2e.test.cjs",
|
||||
"tests/api-coverage.test.cjs",
|
||||
"tests/ask-user-questions-fallback.test.cjs",
|
||||
"tests/audit-command-cutover.test.cjs",
|
||||
"tests/broken-windows.test.cjs",
|
||||
"tests/capability-cli.test.cjs",
|
||||
"tests/capability-command-dispatch.test.cjs",
|
||||
"tests/capability-consent.test.cjs",
|
||||
"tests/capability-ledger.test.cjs",
|
||||
"tests/capability-lifecycle.test.cjs",
|
||||
"tests/capability-loader.test.cjs",
|
||||
"tests/capability-lock-mkdir-failure-3987.test.cjs",
|
||||
"tests/capability-registry.test.cjs",
|
||||
"tests/capability-source.test.cjs",
|
||||
"tests/capability-state.test.cjs",
|
||||
"tests/capability-trust.test.cjs",
|
||||
"tests/changeset-parse.test.cjs",
|
||||
"tests/check-contract-drift.test.cjs",
|
||||
"tests/check-ui-safety-gate.test.cjs",
|
||||
"tests/check-update-config-dir.test.cjs",
|
||||
"tests/chunked-planning-parallel.test.cjs",
|
||||
"tests/ci-docs-guard-registry.test.cjs",
|
||||
"tests/ci-test-scope.test.cjs",
|
||||
"tests/cline-install.test.cjs",
|
||||
"tests/code-review-pipeline-regression.test.cjs",
|
||||
"tests/codex-config-agents.test.cjs",
|
||||
"tests/codex-config-hooks.test.cjs",
|
||||
"tests/codex-config-install.test.cjs",
|
||||
"tests/codex-config.test.cjs",
|
||||
"tests/commands.test.cjs",
|
||||
"tests/commit-docs-bypass.test.cjs",
|
||||
"tests/commit-files-pathspec.test.cjs",
|
||||
"tests/commonjs-marker.test.cjs",
|
||||
"tests/completion-ratio-scope-withholding.test.cjs",
|
||||
"tests/config-loader.test.cjs",
|
||||
"tests/config-schema.property.test.cjs",
|
||||
"tests/config.test.cjs",
|
||||
"tests/contributor-standards.test.cjs",
|
||||
"tests/core-utils.test.cjs",
|
||||
"tests/cursor-subagent-isolation.test.cjs",
|
||||
"tests/debugger-semantic-recall.test.cjs",
|
||||
"tests/default-flip-documentation-lint.test.cjs",
|
||||
"tests/discuss-phase-power.test.cjs",
|
||||
"tests/docs-parity-live-registry.test.cjs",
|
||||
"tests/effort-surface-axis.test.cjs",
|
||||
"tests/effort-sync-installed-runtime.test.cjs",
|
||||
"tests/emitted-attribution.test.cjs",
|
||||
"tests/ensure-runtime-build.test.cjs",
|
||||
"tests/executed-plan.test.cjs",
|
||||
"tests/executor-mvp-tdd-section.test.cjs",
|
||||
"tests/external-job.test.cjs",
|
||||
"tests/failing-direction.test.cjs",
|
||||
"tests/fallow-runner.test.cjs",
|
||||
"tests/feat-2483-review-claude-mds-guard.test.cjs",
|
||||
"tests/features-index-gate.test.cjs",
|
||||
"tests/frontmatter.unit.test.cjs",
|
||||
"tests/gap-checker.property.test.cjs",
|
||||
"tests/gen-context-index.test.cjs",
|
||||
"tests/gen-section-manifest.test.cjs",
|
||||
"tests/git-base-branch.test.cjs",
|
||||
"tests/graphify-query.test.cjs",
|
||||
"tests/graphify-visualization.test.cjs",
|
||||
"tests/gsd-secret-read-guard.test.cjs",
|
||||
"tests/gsd-settings-advanced.test.cjs",
|
||||
"tests/gsd-statusline.test.cjs",
|
||||
"tests/gsd-tools-path-refs.test.cjs",
|
||||
"tests/gsd-validate-commit-crash-policy.test.cjs",
|
||||
"tests/gsd-write-guard.test.cjs",
|
||||
"tests/health-diagnostic-rules/worktree-health.test.cjs",
|
||||
"tests/health-diagnostic.test.cjs",
|
||||
"tests/helpers-cleanup.test.cjs",
|
||||
"tests/helpers-process-isolation.test.cjs",
|
||||
"tests/hooks-crash-policy.test.cjs",
|
||||
"tests/hooks-opt-in.test.cjs",
|
||||
"tests/host-integration.test.cjs",
|
||||
"tests/init-manager.test.cjs",
|
||||
"tests/init.test.cjs",
|
||||
"tests/install-minimal-hooks.test.cjs",
|
||||
"tests/install-path-detection.test.cjs",
|
||||
"tests/install-regressions.test.cjs",
|
||||
"tests/install-runtime-artifacts.test.cjs",
|
||||
"tests/install-write-confinement.test.cjs",
|
||||
"tests/install.test.cjs",
|
||||
"tests/installer-migration-antigravity-retire-confighome-artifacts.test.cjs",
|
||||
"tests/installer-migration-config-root-marker.test.cjs",
|
||||
"tests/installer-migration-pi-retire-hooks-dir.test.cjs",
|
||||
"tests/installer-migration-prune-stale-pristine.test.cjs",
|
||||
"tests/installer-migration-rename-gsd-core.test.cjs",
|
||||
"tests/installer-migrations.test.cjs",
|
||||
"tests/intel.test.cjs",
|
||||
"tests/inventory-nested-families.test.cjs",
|
||||
"tests/isolation-sentinel.test.cjs",
|
||||
"tests/issue-version-gate.test.cjs",
|
||||
"tests/kimi-upgrades.test.cjs",
|
||||
"tests/lint-docs-command-form.test.cjs",
|
||||
"tests/lint-workflow-shellcheck-fetch.test.cjs",
|
||||
"tests/list-seeds.test.cjs",
|
||||
"tests/markdown-sectionizer.test.cjs",
|
||||
"tests/mcp-catalog.test.cjs",
|
||||
"tests/milestone-archive.test.cjs",
|
||||
"tests/milestone-window-single-owner.test.cjs",
|
||||
"tests/model-catalog.unit.test.cjs",
|
||||
"tests/model-resolver.test.cjs",
|
||||
"tests/no-exact-case-env-access.rule.test.cjs",
|
||||
"tests/no-pending-3212-markers.test.cjs",
|
||||
"tests/no-phantom-issue-refs.test.cjs",
|
||||
"tests/no-posix-mode-bit-assert.rule.test.cjs",
|
||||
"tests/no-private-binary-resolution.rule.test.cjs",
|
||||
"tests/no-unguarded-nonportable-exec.rule.test.cjs",
|
||||
"tests/observability/event.test.cjs",
|
||||
"tests/onboard-command.test.cjs",
|
||||
"tests/opencode-plugin-adapter.test.cjs",
|
||||
"tests/pause-work-context-detection.test.cjs",
|
||||
"tests/pause-work-improvements.test.cjs",
|
||||
"tests/perf-317-context-monitor-fs.test.cjs",
|
||||
"tests/phase-completion-single-owner.test.cjs",
|
||||
"tests/phase-estimation.test.cjs",
|
||||
"tests/phase-id-drift-guard.test.cjs",
|
||||
"tests/phase-id.test.cjs",
|
||||
"tests/phase-locator.test.cjs",
|
||||
"tests/phase.test.cjs",
|
||||
"tests/plan-count-single-owner.test.cjs",
|
||||
"tests/plan-phase-stall-detection.test.cjs",
|
||||
"tests/plan-review-convergence.test.cjs",
|
||||
"tests/planning-inspect.test.cjs",
|
||||
"tests/planning-inspect.unit.test.cjs",
|
||||
"tests/planning-lock-mkdir-failure-1884.test.cjs",
|
||||
"tests/planning-snapshot.test.cjs",
|
||||
"tests/planning-workspace.test.cjs",
|
||||
"tests/platform-conformance-tier.test.cjs",
|
||||
"tests/plugin-manifest.test.cjs",
|
||||
"tests/policy-shell-pinning.test.cjs",
|
||||
"tests/portability-rule-disable-ban.test.cjs",
|
||||
"tests/precommit-alias-drift-hook.test.cjs",
|
||||
"tests/prepush-enterprise-email-hook.test.cjs",
|
||||
"tests/process-seam.test.cjs",
|
||||
"tests/profile-output.test.cjs",
|
||||
"tests/profile-pipeline.test.cjs",
|
||||
"tests/quick-batch.test.cjs",
|
||||
"tests/quick-branching.test.cjs",
|
||||
"tests/quick-research.test.cjs",
|
||||
"tests/reapply-verify-hunks.test.cjs",
|
||||
"tests/refactor-1390-t3-characterization.test.cjs",
|
||||
"tests/require-issue-link-policy.test.cjs",
|
||||
"tests/response-language-coverage.test.cjs",
|
||||
"tests/retired-artifact-cleanup.test.cjs",
|
||||
"tests/review-build-prompt-optional-sections.test.cjs",
|
||||
"tests/review-lane-runner.test.cjs",
|
||||
"tests/review-lane-windows-spawn-resolution.test.cjs",
|
||||
"tests/review-parallel-lanes.test.cjs",
|
||||
"tests/review-plan-coverage-manifest.test.cjs",
|
||||
"tests/review-reviewer-selection.test.cjs",
|
||||
"tests/reviewer-manifest-body.test.cjs",
|
||||
"tests/reviewer-step-dispatch.test.cjs",
|
||||
"tests/roadmap-mode-field.test.cjs",
|
||||
"tests/roadmap-parser.test.cjs",
|
||||
"tests/roadmap-phase-fallback.test.cjs",
|
||||
"tests/roadmap.test.cjs",
|
||||
"tests/runtime-artifact-layout.test.cjs",
|
||||
"tests/runtime-identity.test.cjs",
|
||||
"tests/runtime-launcher-parity.test.cjs",
|
||||
"tests/security.test.cjs",
|
||||
"tests/settings-jsonc.test.cjs",
|
||||
"tests/shared-hooks-dir-resolution.test.cjs",
|
||||
"tests/shell-command-projection-dispatch.test.cjs",
|
||||
"tests/spawn-liveness-banner.test.cjs",
|
||||
"tests/state-document.test.cjs",
|
||||
"tests/state-transition.test.cjs",
|
||||
"tests/state.test.cjs",
|
||||
"tests/todos-workstream-scope.test.cjs",
|
||||
"tests/tracer-bullet.test.cjs",
|
||||
"tests/uat.test.cjs",
|
||||
"tests/ui-safety-gate.test.cjs",
|
||||
"tests/ui-spec-inventory-provenance.test.cjs",
|
||||
"tests/unreachable-guard-drift.test.cjs",
|
||||
"tests/unreachable-shell-guard.test.cjs",
|
||||
"tests/unusable-input.test.cjs",
|
||||
"tests/update-custom-backup.test.cjs",
|
||||
"tests/user-artifact-staging.test.cjs",
|
||||
"tests/verification-overrides.test.cjs",
|
||||
"tests/verification-status.test.cjs",
|
||||
"tests/verify-archive-dirs-live-path.test.cjs",
|
||||
"tests/verify-command-grounding.test.cjs",
|
||||
"tests/verify.test.cjs",
|
||||
"tests/workflow-fragments.test.cjs",
|
||||
"tests/workflow-shell-pinning.test.cjs",
|
||||
"tests/workstream-inventory.test.cjs",
|
||||
"tests/workstream.test.cjs",
|
||||
"tests/worktree-safety.test.cjs",
|
||||
"tests/worktree.test.cjs",
|
||||
],
|
||||
};
|
||||
1
tests/fixtures/install-tree/antigravity.json
vendored
1
tests/fixtures/install-tree/antigravity.json
vendored
@@ -622,6 +622,7 @@
|
||||
"scripts/lib/cli-exit.cjs",
|
||||
"scripts/lib/drift-scan.cjs",
|
||||
"scripts/lib/exit-code-registry.cjs",
|
||||
"scripts/lib/macos-conformance-tier.generated.cjs",
|
||||
"scripts/lib/ndjson-reporter.cjs",
|
||||
"scripts/lib/npm-version-check-diagnosis.cjs",
|
||||
"scripts/lib/platform-conformance-tier.generated.cjs",
|
||||
|
||||
1
tests/fixtures/install-tree/augment.json
vendored
1
tests/fixtures/install-tree/augment.json
vendored
@@ -693,6 +693,7 @@
|
||||
"scripts/lib/cli-exit.cjs",
|
||||
"scripts/lib/drift-scan.cjs",
|
||||
"scripts/lib/exit-code-registry.cjs",
|
||||
"scripts/lib/macos-conformance-tier.generated.cjs",
|
||||
"scripts/lib/ndjson-reporter.cjs",
|
||||
"scripts/lib/npm-version-check-diagnosis.cjs",
|
||||
"scripts/lib/platform-conformance-tier.generated.cjs",
|
||||
|
||||
@@ -557,6 +557,7 @@
|
||||
"scripts/lib/cli-exit.cjs",
|
||||
"scripts/lib/drift-scan.cjs",
|
||||
"scripts/lib/exit-code-registry.cjs",
|
||||
"scripts/lib/macos-conformance-tier.generated.cjs",
|
||||
"scripts/lib/ndjson-reporter.cjs",
|
||||
"scripts/lib/npm-version-check-diagnosis.cjs",
|
||||
"scripts/lib/platform-conformance-tier.generated.cjs",
|
||||
|
||||
1
tests/fixtures/install-tree/claude.json
vendored
1
tests/fixtures/install-tree/claude.json
vendored
@@ -621,6 +621,7 @@
|
||||
"scripts/lib/cli-exit.cjs",
|
||||
"scripts/lib/drift-scan.cjs",
|
||||
"scripts/lib/exit-code-registry.cjs",
|
||||
"scripts/lib/macos-conformance-tier.generated.cjs",
|
||||
"scripts/lib/ndjson-reporter.cjs",
|
||||
"scripts/lib/npm-version-check-diagnosis.cjs",
|
||||
"scripts/lib/platform-conformance-tier.generated.cjs",
|
||||
|
||||
1
tests/fixtures/install-tree/cline.json
vendored
1
tests/fixtures/install-tree/cline.json
vendored
@@ -583,6 +583,7 @@
|
||||
"scripts/lib/cli-exit.cjs",
|
||||
"scripts/lib/drift-scan.cjs",
|
||||
"scripts/lib/exit-code-registry.cjs",
|
||||
"scripts/lib/macos-conformance-tier.generated.cjs",
|
||||
"scripts/lib/ndjson-reporter.cjs",
|
||||
"scripts/lib/npm-version-check-diagnosis.cjs",
|
||||
"scripts/lib/platform-conformance-tier.generated.cjs",
|
||||
|
||||
1
tests/fixtures/install-tree/codebuddy.json
vendored
1
tests/fixtures/install-tree/codebuddy.json
vendored
@@ -693,6 +693,7 @@
|
||||
"scripts/lib/cli-exit.cjs",
|
||||
"scripts/lib/drift-scan.cjs",
|
||||
"scripts/lib/exit-code-registry.cjs",
|
||||
"scripts/lib/macos-conformance-tier.generated.cjs",
|
||||
"scripts/lib/ndjson-reporter.cjs",
|
||||
"scripts/lib/npm-version-check-diagnosis.cjs",
|
||||
"scripts/lib/platform-conformance-tier.generated.cjs",
|
||||
|
||||
1
tests/fixtures/install-tree/codex.json
vendored
1
tests/fixtures/install-tree/codex.json
vendored
@@ -621,6 +621,7 @@
|
||||
"scripts/lib/cli-exit.cjs",
|
||||
"scripts/lib/drift-scan.cjs",
|
||||
"scripts/lib/exit-code-registry.cjs",
|
||||
"scripts/lib/macos-conformance-tier.generated.cjs",
|
||||
"scripts/lib/ndjson-reporter.cjs",
|
||||
"scripts/lib/npm-version-check-diagnosis.cjs",
|
||||
"scripts/lib/platform-conformance-tier.generated.cjs",
|
||||
|
||||
1
tests/fixtures/install-tree/copilot.json
vendored
1
tests/fixtures/install-tree/copilot.json
vendored
@@ -583,6 +583,7 @@
|
||||
"scripts/lib/cli-exit.cjs",
|
||||
"scripts/lib/drift-scan.cjs",
|
||||
"scripts/lib/exit-code-registry.cjs",
|
||||
"scripts/lib/macos-conformance-tier.generated.cjs",
|
||||
"scripts/lib/ndjson-reporter.cjs",
|
||||
"scripts/lib/npm-version-check-diagnosis.cjs",
|
||||
"scripts/lib/platform-conformance-tier.generated.cjs",
|
||||
|
||||
1
tests/fixtures/install-tree/cursor.json
vendored
1
tests/fixtures/install-tree/cursor.json
vendored
@@ -594,6 +594,7 @@
|
||||
"scripts/lib/cli-exit.cjs",
|
||||
"scripts/lib/drift-scan.cjs",
|
||||
"scripts/lib/exit-code-registry.cjs",
|
||||
"scripts/lib/macos-conformance-tier.generated.cjs",
|
||||
"scripts/lib/ndjson-reporter.cjs",
|
||||
"scripts/lib/npm-version-check-diagnosis.cjs",
|
||||
"scripts/lib/platform-conformance-tier.generated.cjs",
|
||||
|
||||
1
tests/fixtures/install-tree/hermes.json
vendored
1
tests/fixtures/install-tree/hermes.json
vendored
@@ -621,6 +621,7 @@
|
||||
"scripts/lib/cli-exit.cjs",
|
||||
"scripts/lib/drift-scan.cjs",
|
||||
"scripts/lib/exit-code-registry.cjs",
|
||||
"scripts/lib/macos-conformance-tier.generated.cjs",
|
||||
"scripts/lib/ndjson-reporter.cjs",
|
||||
"scripts/lib/npm-version-check-diagnosis.cjs",
|
||||
"scripts/lib/platform-conformance-tier.generated.cjs",
|
||||
|
||||
1
tests/fixtures/install-tree/kilo.json
vendored
1
tests/fixtures/install-tree/kilo.json
vendored
@@ -696,6 +696,7 @@
|
||||
"scripts/lib/cli-exit.cjs",
|
||||
"scripts/lib/drift-scan.cjs",
|
||||
"scripts/lib/exit-code-registry.cjs",
|
||||
"scripts/lib/macos-conformance-tier.generated.cjs",
|
||||
"scripts/lib/ndjson-reporter.cjs",
|
||||
"scripts/lib/npm-version-check-diagnosis.cjs",
|
||||
"scripts/lib/platform-conformance-tier.generated.cjs",
|
||||
|
||||
1
tests/fixtures/install-tree/kimi-code.json
vendored
1
tests/fixtures/install-tree/kimi-code.json
vendored
@@ -622,6 +622,7 @@
|
||||
"scripts/lib/cli-exit.cjs",
|
||||
"scripts/lib/drift-scan.cjs",
|
||||
"scripts/lib/exit-code-registry.cjs",
|
||||
"scripts/lib/macos-conformance-tier.generated.cjs",
|
||||
"scripts/lib/ndjson-reporter.cjs",
|
||||
"scripts/lib/npm-version-check-diagnosis.cjs",
|
||||
"scripts/lib/platform-conformance-tier.generated.cjs",
|
||||
|
||||
1
tests/fixtures/install-tree/kimi.json
vendored
1
tests/fixtures/install-tree/kimi.json
vendored
@@ -589,6 +589,7 @@
|
||||
"scripts/lib/cli-exit.cjs",
|
||||
"scripts/lib/drift-scan.cjs",
|
||||
"scripts/lib/exit-code-registry.cjs",
|
||||
"scripts/lib/macos-conformance-tier.generated.cjs",
|
||||
"scripts/lib/ndjson-reporter.cjs",
|
||||
"scripts/lib/npm-version-check-diagnosis.cjs",
|
||||
"scripts/lib/platform-conformance-tier.generated.cjs",
|
||||
|
||||
1
tests/fixtures/install-tree/opencode.json
vendored
1
tests/fixtures/install-tree/opencode.json
vendored
@@ -696,6 +696,7 @@
|
||||
"scripts/lib/cli-exit.cjs",
|
||||
"scripts/lib/drift-scan.cjs",
|
||||
"scripts/lib/exit-code-registry.cjs",
|
||||
"scripts/lib/macos-conformance-tier.generated.cjs",
|
||||
"scripts/lib/ndjson-reporter.cjs",
|
||||
"scripts/lib/npm-version-check-diagnosis.cjs",
|
||||
"scripts/lib/platform-conformance-tier.generated.cjs",
|
||||
|
||||
1
tests/fixtures/install-tree/pi.json
vendored
1
tests/fixtures/install-tree/pi.json
vendored
@@ -423,6 +423,7 @@
|
||||
"scripts/lib/cli-exit.cjs",
|
||||
"scripts/lib/drift-scan.cjs",
|
||||
"scripts/lib/exit-code-registry.cjs",
|
||||
"scripts/lib/macos-conformance-tier.generated.cjs",
|
||||
"scripts/lib/ndjson-reporter.cjs",
|
||||
"scripts/lib/npm-version-check-diagnosis.cjs",
|
||||
"scripts/lib/platform-conformance-tier.generated.cjs",
|
||||
|
||||
1
tests/fixtures/install-tree/qwen.json
vendored
1
tests/fixtures/install-tree/qwen.json
vendored
@@ -621,6 +621,7 @@
|
||||
"scripts/lib/cli-exit.cjs",
|
||||
"scripts/lib/drift-scan.cjs",
|
||||
"scripts/lib/exit-code-registry.cjs",
|
||||
"scripts/lib/macos-conformance-tier.generated.cjs",
|
||||
"scripts/lib/ndjson-reporter.cjs",
|
||||
"scripts/lib/npm-version-check-diagnosis.cjs",
|
||||
"scripts/lib/platform-conformance-tier.generated.cjs",
|
||||
|
||||
1
tests/fixtures/install-tree/trae.json
vendored
1
tests/fixtures/install-tree/trae.json
vendored
@@ -581,6 +581,7 @@
|
||||
"scripts/lib/cli-exit.cjs",
|
||||
"scripts/lib/drift-scan.cjs",
|
||||
"scripts/lib/exit-code-registry.cjs",
|
||||
"scripts/lib/macos-conformance-tier.generated.cjs",
|
||||
"scripts/lib/ndjson-reporter.cjs",
|
||||
"scripts/lib/npm-version-check-diagnosis.cjs",
|
||||
"scripts/lib/platform-conformance-tier.generated.cjs",
|
||||
|
||||
1
tests/fixtures/install-tree/windsurf.json
vendored
1
tests/fixtures/install-tree/windsurf.json
vendored
@@ -516,6 +516,7 @@
|
||||
"scripts/lib/cli-exit.cjs",
|
||||
"scripts/lib/drift-scan.cjs",
|
||||
"scripts/lib/exit-code-registry.cjs",
|
||||
"scripts/lib/macos-conformance-tier.generated.cjs",
|
||||
"scripts/lib/ndjson-reporter.cjs",
|
||||
"scripts/lib/npm-version-check-diagnosis.cjs",
|
||||
"scripts/lib/platform-conformance-tier.generated.cjs",
|
||||
|
||||
1
tests/fixtures/install-tree/zcode.json
vendored
1
tests/fixtures/install-tree/zcode.json
vendored
@@ -653,6 +653,7 @@
|
||||
"scripts/lib/cli-exit.cjs",
|
||||
"scripts/lib/drift-scan.cjs",
|
||||
"scripts/lib/exit-code-registry.cjs",
|
||||
"scripts/lib/macos-conformance-tier.generated.cjs",
|
||||
"scripts/lib/ndjson-reporter.cjs",
|
||||
"scripts/lib/npm-version-check-diagnosis.cjs",
|
||||
"scripts/lib/platform-conformance-tier.generated.cjs",
|
||||
|
||||
@@ -22,11 +22,18 @@ const path = require('node:path');
|
||||
|
||||
const { createTempDir, cleanup } = require('./helpers.cjs');
|
||||
const { runNode } = require('./helpers/process-seam.cjs');
|
||||
const { classifyContent, classifyTree, NOISY_FOR_SOURCE_REACHABILITY } = require('../scripts/gen-platform-conformance-tier.cjs');
|
||||
const {
|
||||
classifyContent,
|
||||
classifyTree,
|
||||
NOISY_FOR_SOURCE_REACHABILITY,
|
||||
classifyMacosContent,
|
||||
classifyMacosTree,
|
||||
} = require('../scripts/gen-platform-conformance-tier.cjs');
|
||||
|
||||
const ROOT = path.resolve(__dirname, '..');
|
||||
const SCRIPT = path.join(ROOT, 'scripts', 'gen-platform-conformance-tier.cjs');
|
||||
const GENERATED_PATH = path.join(ROOT, 'scripts', 'lib', 'platform-conformance-tier.generated.cjs');
|
||||
const MACOS_GENERATED_PATH = path.join(ROOT, 'scripts', 'lib', 'macos-conformance-tier.generated.cjs');
|
||||
|
||||
// ─── Rows 1-15: classifyContent, pure fixtures ────────────────────────────────
|
||||
|
||||
@@ -319,3 +326,188 @@ describe('gen-platform-conformance-tier.cjs — real repo tree (regression)', ()
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// ─── #4593: macOS-specific classifier (classifyMacosContent / MACOS_CATEGORIES)
|
||||
|
||||
describe('classifyMacosContent — happy-path signals', () => {
|
||||
test('flags darwin literal', () => {
|
||||
const { needsRealOs, signals } = classifyMacosContent("const platforms = ['darwin', 'linux'];");
|
||||
assert.equal(needsRealOs, true);
|
||||
assert.ok(signals.includes('darwin-literal'));
|
||||
});
|
||||
|
||||
test('flags zsh dispatch', () => {
|
||||
const { needsRealOs, signals } = classifyMacosContent("shell: 'zsh {0}'");
|
||||
assert.equal(needsRealOs, true);
|
||||
assert.ok(signals.includes('zsh-dispatch'));
|
||||
});
|
||||
|
||||
test('flags case-sensitivity phrasing', () => {
|
||||
for (const fixture of [
|
||||
'// verify the case-insensitive lookup',
|
||||
'// verify the case-sensitive lookup',
|
||||
'// verify case insensitivity',
|
||||
]) {
|
||||
const { needsRealOs, signals } = classifyMacosContent(fixture);
|
||||
assert.equal(needsRealOs, true, fixture);
|
||||
assert.ok(signals.includes('case-sensitivity'), fixture);
|
||||
}
|
||||
});
|
||||
|
||||
test('flags chmod mode-bit octal', () => {
|
||||
const { needsRealOs, signals } = classifyMacosContent('fs.chmodSync(target, 0o755);');
|
||||
assert.equal(needsRealOs, true);
|
||||
assert.ok(signals.includes('chmod-mode-bit'));
|
||||
});
|
||||
|
||||
test('flags symlink keyword', () => {
|
||||
const { needsRealOs, signals } = classifyMacosContent('fs.symlinkSync(target, link);');
|
||||
assert.equal(needsRealOs, true);
|
||||
assert.ok(signals.includes('symlink-keyword'));
|
||||
});
|
||||
});
|
||||
|
||||
describe('classifyMacosContent — negative case', () => {
|
||||
test('does not flag a clean file with none of the 5 macOS signals', () => {
|
||||
const fixture =
|
||||
"const assert = require('node:assert/strict');\n" +
|
||||
"if (process.platform === 'win32') { doThing(); }\n" +
|
||||
"test('adds numbers', () => { assert.equal(1 + 1, 2); });";
|
||||
const { needsRealOs, signals } = classifyMacosContent(fixture);
|
||||
assert.equal(needsRealOs, false);
|
||||
assert.deepEqual(signals, []);
|
||||
});
|
||||
|
||||
test('does not crash on empty content', () => {
|
||||
assert.doesNotThrow(() => classifyMacosContent(''));
|
||||
const { needsRealOs, signals } = classifyMacosContent('');
|
||||
assert.equal(needsRealOs, false);
|
||||
assert.deepEqual(signals, []);
|
||||
});
|
||||
});
|
||||
|
||||
// ─── #4593: CLI --target macos ─────────────────────────────────────────────
|
||||
|
||||
describe('gen-platform-conformance-tier.cjs CLI --target macos (temp fixture tree)', () => {
|
||||
test('--target macos --check passes when the generated file is fresh', () => {
|
||||
const tmpDir = createTempDir('gen-platform-conformance-tier-macos-');
|
||||
try {
|
||||
const testsDir = path.join(tmpDir, 'tests');
|
||||
fs.mkdirSync(testsDir, { recursive: true });
|
||||
fs.writeFileSync(path.join(testsDir, 'flagged.test.cjs'), 'fs.symlinkSync(target, link);\n');
|
||||
fs.writeFileSync(path.join(testsDir, 'clean.test.cjs'), "assert.equal(1 + 1, 2);\n");
|
||||
const outPath = path.join(tmpDir, 'macos-conformance-tier.generated.cjs');
|
||||
|
||||
const write = runGen(['--target', 'macos', '--write', '--tests-dir', testsDir, '--out', outPath]);
|
||||
assert.equal(write.exitCode, 0, write.stderr);
|
||||
assert.ok(fs.existsSync(outPath));
|
||||
|
||||
delete require.cache[require.resolve(outPath)];
|
||||
const generated = require(outPath);
|
||||
assert.deepEqual(generated.MACOS_CONFORMANCE_TIER_FILES, ['tests/flagged.test.cjs']);
|
||||
|
||||
const check = runGen(['--target', 'macos', '--check', '--tests-dir', testsDir, '--out', outPath]);
|
||||
assert.equal(check.exitCode, 0, check.stderr);
|
||||
assert.match(check.stdout, /ok gen-platform-conformance-tier --target macos/);
|
||||
} finally {
|
||||
cleanup(tmpDir);
|
||||
}
|
||||
});
|
||||
|
||||
test('--target macos --check fails and names the drift when the list is stale', () => {
|
||||
const tmpDir = createTempDir('gen-platform-conformance-tier-macos-');
|
||||
try {
|
||||
const testsDir = path.join(tmpDir, 'tests');
|
||||
fs.mkdirSync(testsDir, { recursive: true });
|
||||
fs.writeFileSync(path.join(testsDir, 'flagged.test.cjs'), 'fs.symlinkSync(target, link);\n');
|
||||
const outPath = path.join(tmpDir, 'macos-conformance-tier.generated.cjs');
|
||||
|
||||
const write = runGen(['--target', 'macos', '--write', '--tests-dir', testsDir, '--out', outPath]);
|
||||
assert.equal(write.exitCode, 0, write.stderr);
|
||||
|
||||
fs.writeFileSync(path.join(testsDir, 'new-signal.test.cjs'), "const platforms = ['darwin'];\n");
|
||||
|
||||
const check = runGen(['--target', 'macos', '--check', '--tests-dir', testsDir, '--out', outPath]);
|
||||
assert.equal(check.exitCode, 1);
|
||||
const combined = check.stdout + check.stderr;
|
||||
assert.match(combined, /tests\/new-signal\.test\.cjs/, 'the drift report must name the new file');
|
||||
} finally {
|
||||
cleanup(tmpDir);
|
||||
}
|
||||
});
|
||||
|
||||
test('a suite-suffixed file is excluded even with a qualifying macOS content signal', () => {
|
||||
const tmpDir = createTempDir('gen-platform-conformance-tier-macos-suite-');
|
||||
try {
|
||||
const testsDir = path.join(tmpDir, 'tests');
|
||||
fs.mkdirSync(testsDir, { recursive: true });
|
||||
const signal = 'fs.symlinkSync(target, link);\n';
|
||||
fs.writeFileSync(path.join(testsDir, 'foo.test.cjs'), signal);
|
||||
fs.writeFileSync(path.join(testsDir, 'foo.install.test.cjs'), signal);
|
||||
const outPath = path.join(tmpDir, 'macos-conformance-tier.generated.cjs');
|
||||
|
||||
const write = runGen(['--target', 'macos', '--write', '--tests-dir', testsDir, '--out', outPath]);
|
||||
assert.equal(write.exitCode, 0, write.stderr);
|
||||
|
||||
delete require.cache[require.resolve(outPath)];
|
||||
const generated = require(outPath);
|
||||
|
||||
assert.deepEqual(
|
||||
generated.MACOS_CONFORMANCE_TIER_FILES,
|
||||
['tests/foo.test.cjs'],
|
||||
'the install-suite file must be excluded even though its content would otherwise qualify',
|
||||
);
|
||||
} finally {
|
||||
cleanup(tmpDir);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// ─── #4593: real tests/ tree, regression against the committed macOS artifact
|
||||
|
||||
describe('gen-platform-conformance-tier.cjs — real repo tree, macOS target (regression)', () => {
|
||||
test('real tests/ tree macOS classification matches the committed list', () => {
|
||||
const realTestsDir = path.join(ROOT, 'tests');
|
||||
|
||||
let fresh;
|
||||
assert.doesNotThrow(() => {
|
||||
fresh = classifyMacosTree(realTestsDir);
|
||||
}, 'a full sweep of the real tests/ tree must complete without throwing');
|
||||
|
||||
// Measured 196/930 at authoring time (#4593 design doc). Sanity ballpark
|
||||
// with headroom for organic test-suite growth, not a brittle exact match.
|
||||
assert.ok(
|
||||
fresh.files.length >= 100 && fresh.files.length <= 350,
|
||||
`expected a real, current, sanity-checked count in [100, 350], got ${fresh.files.length}`,
|
||||
);
|
||||
|
||||
delete require.cache[require.resolve(MACOS_GENERATED_PATH)];
|
||||
const committed = require(MACOS_GENERATED_PATH);
|
||||
|
||||
assert.equal(
|
||||
committed.MACOS_CONFORMANCE_TIER_FILES.length,
|
||||
fresh.files.length,
|
||||
'the committed macOS generated file must be fresh — run ' +
|
||||
'`node scripts/gen-platform-conformance-tier.cjs --target macos --write`',
|
||||
);
|
||||
assert.deepEqual(
|
||||
committed.MACOS_CONFORMANCE_TIER_FILES.slice().sort(),
|
||||
fresh.files.slice().sort(),
|
||||
'the committed macOS list must match a fresh sweep exactly, not just in length',
|
||||
);
|
||||
});
|
||||
|
||||
test('the committed macOS conformance-tier list contains zero suite-tagged files', () => {
|
||||
delete require.cache[require.resolve(MACOS_GENERATED_PATH)];
|
||||
const { MACOS_CONFORMANCE_TIER_FILES } = require(MACOS_GENERATED_PATH);
|
||||
|
||||
const suiteTaggedPattern = /\.(install|security|slow|integration|qa)\.test\.cjs$/;
|
||||
const offenders = MACOS_CONFORMANCE_TIER_FILES.filter((f) => suiteTaggedPattern.test(f));
|
||||
|
||||
assert.deepEqual(
|
||||
offenders,
|
||||
[],
|
||||
'suite-tagged files must never appear in the macOS conformance-tier list either',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user