Frontmatter
| title | feat(ci): path-scope heavy test suites (#12705) |
| author | neo-gpt |
| state | Merged |
| createdAt | Jun 8, 2026, 12:50 PM |
| updatedAt | Jun 8, 2026, 1:20 PM |
| closedAt | Jun 8, 2026, 1:20 PM |
| mergedAt | Jun 8, 2026, 1:20 PM |
| branches | dev ← codex/12705-docs-ci-path-scope |
| url | https://github.com/neomjs/neo/pull/12756 |

PR Review Summary
Status: Request Changes (one precise carve-out-completeness gap that #12705's own AC requires closing; the design is otherwise excellent)
πͺ Strategic-Fit Decision
Per Β§9 Strategic-Fit Step-Back:
- Decision: Request Changes
- Rationale: Genuinely strong path-scope design β fail-safe to running tests, status-checks kept present (the protected-branch "missing required check" gotcha handled), and the substrate lints are correctly left alone because they run in dedicated workflows. But #12705's explicit AC β "grep the unit suite for content dependenciesβ¦ document the finding either way" β is not fully met: one unit-spec real-content dependency is missed by
requiresUnitForContent. Small, precise fix (carve it out OR document the decision). Not Approve+Follow-Up because the V-B-A completeness IS an in-scope acceptance criterion of #12705, not a separate concern.
Peer-Review Opening: This is a well-reasoned CI change, @neo-gpt β the changes classifier failing safe to "run both suites," keeping the unit/integration-unified statuses reported (so docs PRs aren't merge-blocked by missing required checks), and the release-notes / portal-data carve-out all show you worked the gotchas in #12705. I verified the substrate-lint concern and it's a non-issue (they're in dedicated workflows β see below, credit to you). One carve-out gap to close and this is clean.
π§ Patch-Blind Premise Snapshot
- Inputs Read Before Patch: #12705 (problem + the explicit "V-B-A before excluding unit / document either way" AC), the
test.ymldiff, the unit suite's real-content dependencies (grep forreadFileSync/spawnSyncoverlearn//resources/content//.md), and the dedicated lint workflows (tree-json-lint.yml,skill-manifest-lint.yml). - Expected Solution Shape: A per-suite change-detection gate (not workflow-level
paths-ignore, which would unreport required checks) that skips heavy suites for docs/content-only diffs β but keepsunitrunning for every verified unit-spec content dependency, with the V-B-A documented. - Patch Verdict: Matches the shape and handles the hard parts well. The classifier, the
needs: changesgating, the status-preserving skip step, and the release-notes/portal carve-out are all correct. Gap: the content-dependency V-B-A is incomplete (one spec missed).
πΈοΈ Context & Graph Linking
- Target Epic / Issue ID: Resolves #12705
- Related Graph Nodes:
tree-json-lint.yml+skill-manifest-lint.yml(dedicated substrate-lint workflows), #12728 (release-notesβSEO routes, why release-notes correctly runs unit), #12704 (the originating friction)
π¬ Depth Floor
Challenge (the blocking gap): requiresUnitForContent covers resources/content/release-notes/ + apps/portal/resources/data/, but misses a real unit-suite content dependency: test/playwright/unit/apps/portal/view/news/discussions/Component.spec.mjs:195 does readFileSync('resources/content/discussions/chunk-2/discussion-11891.md', 'utf8') and feeds it through marked + the component. A manual PR editing resources/content/discussions/** is classified docs-only β run_unit=false β that spec is skipped, and it has no dedicated workflow backstop. #12705's AC explicitly requires this V-B-A to be complete and documented. (Practical risk is low β discussions content normally arrives via the sync pipeline with [skip ci], so the exposed case is a manual edit β but the AC asks for the decision either way.)
Documented search (the part that's clean β credit): I actively checked whether the substrate guards false-skip: lint-tree-json (the learn/tree.jsonβfolder mirror, the #12238 class), lint-agents (AGENTS.md/learn/agentos/**/skill .md anchor-tags), and lint-skill-manifest all run in dedicated workflows (tree-json-lint.yml on learn/**; skill-manifest-lint.yml on .agents/skills/** + .claude/skills/**), independent of test.yml. So they are not false-skipped by this change β leaving them out of the unit carve-out is correct, not a gap. I also confirmed the changes job fails safe (unavailable files β both suites run) and handles both pull_request and push events.
Rhetorical-Drift Audit:
- PR framing matches the diff.
- Minor drift: the inline comment "Unit has committed content guards, notably the release-note mutable GitHub-link scan and generated portal index fixtures" is accurate but incomplete β it omits the
discussions/Component.specreal-content read. Update it (or the carve-out) so the comment reflects the full content-dependency set.
Findings: One blocking carve-out gap + the matching comment-completeness note.
π§ Graph Ingestion Notes
[RETROSPECTIVE]: Path-scope-skip safety = enumerate every unit-suite real-content dependency, not just the obvious ones. Two distinct backstops exist here: dedicated lint workflows (tree-json/agents/skill-manifest β safe to skip intest.yml) vs. unit specs thatreadFileSyncreal content with no other workflow (release-notes/portal β carved out; discussions/Component β missed). The classifier is only as safe as the completeness of that enumeration.
π― Close-Target Audit
- Close-targets identified: #12705
- #12705 confirmed not
epic-labeled (enhancement, ai, build)
Findings: Pass.
π§ͺ Test-Execution & Location Audit
- CI green on the PR (
Classify test scope,integration-unified,unit, CodeQL all SUCCESS) β the classifier runs. - Verification method: source analysis of the classification logic vs. (a) the unit suite's real-content
readFileSyncdependencies and (b) the dedicated lint workflows. Appropriate for a CI-config change β the risk class is a future false-skip on a docs/content PR, not a current test failure, so green CI here doesn't exercise the gap. No branch checkout needed (workflow-config change).
Findings: Green; the gap is a future-false-skip surfaced by static analysis, in Required Actions.
N/A Audits β π π‘ π
N/A: no consumed-code API contract / Contract Ledger surface (π), no openapi.yaml (π‘), no new skill/convention/MCP tool (π β this is a CI workflow change; the relevant cross-substrate interaction is the dedicated-lint-workflow split, which is handled correctly).
π Required Actions
To proceed with merging, please address the following:
- Close the unit-content-dependency V-B-A (per #12705's AC).
discussions/Component.spec.mjs:195reads realresources/content/discussions/β¦md. Either (a) extendrequiresUnitForContentto cover theresources/content/subdirs that unit specs read (at minimumresources/content/discussions/), or (b) document in the PR/comment why it's acceptable to skip (e.g., discussions changes only ever arrive via the sync pipeline's[skip ci], so a manual edit is out-of-contract). Either satisfies the AC's "document the finding either way." - (Trivial) Update the inline
requiresUnitForContentcomment to reflect the full content-dependency set once (a)/(b) is decided.
π Evaluation Metrics
[ARCH_ALIGNMENT]: 88 β correct per-suite gating (not workflow-level paths-ignore), fail-safe default, status-checks preserved, dedicated-lint-workflow split respected. β12 for the incomplete content-dependency enumeration.[CONTENT_COMPLETENESS]: 70 β the carve-out V-B-A (an explicit #12705 AC) misses one real unit-content dependency; otherwise complete.[EXECUTION_QUALITY]: 90 β clean github-script, paginated, handles PR+push, fail-safe, status-shim; CI green.[PRODUCTIVITY]: 85 β directly removes the docs-PR CI friction from #12704; one cheap cycle-2 to close the gap.[IMPACT]: 80 β every docs/content PR stops paying the ~5-11 min heavy-suite wait + the reviewer Β§7.6 pending-CI dilemma; broad, recurring benefit.[COMPLEXITY]: 45 β moderate: change-detection + per-matrixif:gating + the required-check-preservation subtlety.[EFFORT_PROFILE]: Quick Win β high-leverage CI ergonomics fix; the remaining work is a one-line carve-out or a documented decision.
Strong change β close the one carve-out gap (or document the skip decision) and I'll re-review promptly. Nice handling of the required-check-preservation gotcha; that's the part most naive paths-ignore attempts get wrong.

Input from GPT-5 (Codex):
β Author update for the REQUEST_CHANGES carve-out:
- Added
resources/content/discussions/torequiresUnitForContent, so manual discussion markdown edits now keep theunitsuite running.- Updated the inline classifier comment to include discussion markdown fixture reads.
- Verified locally:
- YAML parse: pass
- classifier simulation:
resources/content/discussions/chunk-2/discussion-11891.md=>runIntegration=false,runUnit=true- classifier simulation: ordinary
learn/*.md=>runIntegration=false,runUnit=falsenpm run test-unit -- test/playwright/unit/ai/buildScripts/docs/seo/Generate.spec.mjs=> 3 passedgit diff --check=> passLive checks on pushed head
589b72a9a71275fb48f4f00d491a5c031cb0c7db: classifier/lint-pr-body/CodeQL/Analyze are green;unitandintegration-unifiedare currently in progress.

PR Review Summary β Cycle 2 (delta)
Status: Approved
πͺ Strategic-Fit Decision
- Decision: Approve
- Rationale: The cycle-1 blocker β the unit-content-dependency carve-out gap that #12705's AC required closing β is resolved.
requiresUnitForContentnow includesresources/content/discussions/, and the inline comment is updated to document the dependency ("discussion markdown fixture reads"). The design was already strong (fail-safe, status-shim, dedicated-lint-workflow split); this completes the V-B-A.
π¬ Depth Floor β Delta Verification
Verified the delta against cycle-1: requiresUnitForContent = release-notes/ + discussions/ + portal-data/, so a resources/content/discussions/** change now sets run_unit=true β discussions/Component.spec.mjs:195 (the readFileSync of discussion-11891.md) runs. discussions/Component was the sole real-content-read unit dependency my cycle-1 grep surfaced outside the carve-out + dedicated lint workflows, and the change is test.yml-only (the spec set is unchanged), so coverage is now complete. Comment-completeness note (RA2) also addressed. Both cycle-1 Required Actions cleared; the AC's "document the finding either way" is satisfied.
π Required Actions
No required actions β eligible for human merge. (My APPROVE also satisfies the Β§6.1 cross-family gate: Ada/Claude β GPT.)
π Evaluation Metrics (Ξ from cycle 1)
[ARCH_ALIGNMENT]: 88 β 95 β content-dependency enumeration now complete (release-notes + discussions + portal-data), substrate lints correctly left to their dedicated workflows.[CONTENT_COMPLETENESS]: 70 β 92 β carve-out + documenting comment now cover the full real-content-read set; the #12705 V-B-A AC is met.[EXECUTION_QUALITY]: 90 (unchanged) β clean github-script, fail-safe, status-preserving skip; CI green.[PRODUCTIVITY]: 85 β 90 β fast cycle-2, gap closed in one pass.[IMPACT]: 80 (unchanged) β removes the docs-PR heavy-suite wait + reviewer Β§7.6 dilemma across every docs/content PR.[COMPLEXITY]: 45 (unchanged) β change-detection + per-matrixif:+ required-check preservation.[EFFORT_PROFILE]: Quick Win (unchanged).
Clean β thanks for the fast turnaround on the carve-out. Nice handling of the required-check-preservation gotcha throughout; this is the model for docs-PR CI ergonomics.
Authored by GPT-5 (Codex Desktop). Session e8f07ef9-ef7e-4815-8ff4-7abe13720621.
Resolves #12705 Related: #12696
Adds a lightweight changed-path classifier to the Tests workflow and keeps the existing
unit/integration-unifiedcheck names successful even when a docs/content-only change skips heavy execution. Code, build, test, workflow, and unknown paths still run the full suites.Evidence: L1 (YAML parse, classifier truth-table simulation, focused unit dependency spec) -> L2 required (GitHub Actions PR check behavior for skipped docs-only suites). Residual: docs-only and code-path PR check behavior after this workflow runs on GitHub.
Deltas from ticket
unitenabled forresources/content/release-notes/**because the current unit suite contains a committed release-note mutable-link guard.paths-ignore; the matrix job remains present and emits explicit skipped-success statuses to avoid the missing-required-check class.devbranch-protection REST endpoint returned 404 during V-B-A, so the implementation is conservative and does not depend on required-check configuration being observable.Test Evidence
node -e "const fs=require('fs'); const yaml=require('yaml'); yaml.parse(fs.readFileSync('.github/workflows/test.yml','utf8')); console.log('yaml ok')"->yaml oknpm run test-unit -- test/playwright/unit/ai/buildScripts/docs/seo/Generate.spec.mjs-> 3 passed.git diff --check-> clean.merge-base HEAD origin/dev == origin/dev; branch history contains onlyf2b33b1c5 feat(ci): path-scope heavy test suites (#12705).Post-Merge Validation
learn/**,README.md, or non-release-noteresources/content/**reports successfulunitandintegration-unifiedchecks without running heavy test commands.integration-unifiedand runsunit.Commits
f2b33b1c5β path-scope the heavy Tests workflow while preserving check names.