Skip to content

feat(core-domain): GT-377 AC-3 — ESLint stateless-Core *Repository guard + CI gate#147

Open
beyondnetPeru wants to merge 2 commits into
developfrom
claude/vigorous-gauss-d24b4d
Open

feat(core-domain): GT-377 AC-3 — ESLint stateless-Core *Repository guard + CI gate#147
beyondnetPeru wants to merge 2 commits into
developfrom
claude/vigorous-gauss-d24b4d

Conversation

@beyondnetPeru

Copy link
Copy Markdown
Contributor

GT-377 AC-3 — ESLint stateless-Core *Repository guard, enforcing + CI-gated

Closes the AC-3 acceptance criterion of GT-377: "ESLint boundary guard fails CI if a *Repository for product/initiative/evidence/decision appears."

What this delivers

  • Guard (flat config, ESLint 9): packages/core-domain/eslint.config.mjs bans Identifier[name=/(Product|Initiative|Evidence|Decision)Repository/] via no-restricted-syntax. Core is a stateless Evaluation Engine — those are context, not entities (ADR-0101). Entity-scoped, so legit infra repos (AuditRepository, createRepository, …) are untouched.
  • Single source of truth: the rule lives in packages/core-domain/eslint.guards.cjs, imported by both the config and the test.
  • Negative regression test: src/evaluation/stateless-core-repository.guard.spec.ts — 14 cases proving the guard fires on all four banned entities (import + inline interface) and never on legit *Repository.
  • CI gate: new Run core-domain architecture boundary guard (GT-377) step in .github/workflows/ci-cd.yml (test-core-domain). Before this PR, grep lint:boundaries .github/workflows = 0.
  • Migrated off the ESLint-9-incompatible legacy .eslintrc.js + --no-eslintrc (deleted the dead file); lint:boundaries script → eslint "src/**/*.ts".

Root cause of the long-standing "lint:boundaries broken" note

It was not the boundaries plugin. The root package.json global override "ajv":"8.17.1" conflicts with the workspaces' direct ajv:8.20.0 (EOVERRIDE), so under --legacy-peer-deps npm silently dropped all ajv overrides and collapsed ajv@8 onto eslint/@eslint/eslintrc (which need ajv@6), making ESLint's loader throw missingRefs / Cannot set properties of undefined (setting 'defaultMeta').

Fix: scoped overridesajv aligned to 8.20.0 (== direct dep, no conflict) + carve-outs eslint/@eslint/eslintrcajv@^6.12.6.

⚠️ Touches shared root files — merge-order note for the SDLC closing thread

  • package.json (overrides) and package-lock.json (root).
  • The lockfile change is scoped to the eslint subtree (~82 lines, nested ajv@6.15.0, no cross-workspace drift), produced incrementally and verified under npm ci.
  • High risk of lockfile conflict with the sibling integration branches feat/core-gt377-schemas (AC-1), feat/core-gt379-blueprint-deployment, feat/core-gt382-wasm-path if they also touched the lockfile. Recommend: merge sequentially and reconcile the lockfile at the end with the incremental method (remove only the eslint/@eslint/eslintrc entries from the lockfile + node_modules, then npm install --legacy-peer-deps) — never rm package-lock.json (full re-resolution drifts ~1300 lines, e.g. @types/node 24→26).

GT-377 status

  • AC-2 (types/binding) already MET (prior wave); AC-3 MET here.
  • AC-1 (schemas) is open in feat/core-gt377-schemas — once it lands, GT-377 → DONE. Left as IN-PROGRESS.
  • Gap board + catalog updated (EN/ES).

Verification

npm cinpm run lint:boundaries --workspace @evolith/core-domain = 0 errors; tsc build green; core-domain 692/692 tests; injected ProductRepository correctly fails the guard, AuditRepository does not.

Follow-up (chip filed)

packages/mcp-server and apps/core-api carry the same broken lint:boundaries (--no-eslintrc -c .eslintrc.js), ungated by CI — same migration pattern applies.

🤖 Generated with Claude Code

…an in ESLint + gate CI

Migrate core-domain to ESLint 9 flat config (eslint.config.mjs) and add a
no-restricted-syntax guard banning *Repository identifiers for
product/initiative/evidence/decision — Core is a stateless Evaluation Engine,
those are context not entities (ADR-0101). The rule is shared from
eslint.guards.cjs (single source of truth) and covered by a 14-case negative
regression test (stateless-core-repository.guard.spec.ts) proving it fires on
the four banned entities and never on legit *Repository. Wire lint:boundaries
into ci-cd.yml (test-core-domain); delete the dead .eslintrc.js.

Root cause of the long-standing "lint:boundaries broken" note was NOT the
boundaries plugin: the root global override "ajv":"8.17.1" conflicts with the
workspaces' direct ajv:8.20.0 (EOVERRIDE), so npm dropped all ajv overrides and
starved eslint/@eslint/eslintrc of ajv@6, throwing missingRefs/defaultMeta at
load. Fixed with scoped overrides (ajv aligned to 8.20.0 + eslint/@eslint/eslintrc
carved out to ajv@^6.12.6); lockfile change scoped to the eslint subtree
(~82 lines, no cross-workspace drift), verified under npm ci.

GT-377: AC-2 + AC-3 MET; AC-1 (schemas) still open -> stays IN-PROGRESS.
Gap board + catalog updated (EN/ES).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4ea76378c7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

* if such an identifier is declared, imported, or referenced.
*/
import boundaries from 'eslint-plugin-boundaries';
import tseslint from 'typescript-eslint';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Declare the ESLint config's typescript-eslint dependency

When @evolith/core-domain is installed or linted in isolation, this new flat config imports the typescript-eslint meta-package even though packages/core-domain/package.json only declares @typescript-eslint/parser; the package is currently present only because another workspace (apps/core-api) happens to depend on it. A focused workspace install or future removal from that unrelated package will make npm run lint:boundaries --workspace @evolith/core-domain fail with ERR_MODULE_NOT_FOUND before the boundary guard can run, so core-domain should declare typescript-eslint directly or avoid importing it.

Useful? React with 👍 / 👎.

Reconciles claude/vigorous-gauss-d24b4d (GT-377 AC-3 stateless-Core *Repository
guard) with main. No package.json/lockfile conflict: main already carried the
byte-identical ajv-override fix from the mcp-server/core-api flat-config wave.

Resolved conflicts:
- ci-cd.yml: kept BOTH the core-domain boundary-guard step (GT-377) and the
  GT-382 build:policy step in test-core-domain.
- gap board (EN/ES tracking + catalog): combined waves; with AC-1 (schemas) +
  AC-2 already on main, all three GT-377 ACs are MET -> GT-377 DONE.

lint:boundaries green (0 errors) on the merged tree; core-domain 692/692.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant