Skip to content

feat(harness): agentic-first context & harness-integrity system - #30539

Open
TeddyCr wants to merge 35 commits into
open-metadata:mainfrom
TeddyCr:MINOR-Agentic-First-System
Open

feat(harness): agentic-first context & harness-integrity system#30539
TeddyCr wants to merge 35 commits into
open-metadata:mainfrom
TeddyCr:MINOR-Agentic-First-System

Conversation

@TeddyCr

@TeddyCr TeddyCr commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator

Summary

Restructures the repo's agent-facing context into a layered, self-maintaining system so coding agents (Claude Code, Codex) load the right guidance at the right time — and adds CI that warns when
that guidance drifts from the code. No product/runtime code changes: entirely agent context, docs, tooling, and non-blocking CI.

Motivation

CLAUDE.md had grown into a single ~700-line always-loaded file mixing always-true rules with language/path-specific detail, and nothing caught it drifting from the code. This PR splits
always-loaded guidance from path-scoped rules that auto-load only when you touch a matching file, gives agents a discoverable map of existing docs instead of re-deriving from code, and adds a
warnings-only CI check so dead references / size budgets / broken globs surface on PRs.

What changed

  1. CLAUDE.md → thin map + path-scoped rules — trimmed to a 169-line always-loaded map; nine auto-loading .claude/rules/*.md (java, frontend-react, frontend-styling, component-library, i18n,
    frontend-playwright, python-ingestion, schema-first, migrations), each with a paths: glob.

  2. System & knowledge maps — ARCHITECTURE.md (system map + invariants), docs/index.md (doc index with CURRENT/STALE/SUPERSEDED freshness verified against the tree), docs/design-patterns.md (GoF
    patterns idiomatic to this repo).

  3. Deterministic reference-doc generators — scripts/generate_entity_index.py → docs/generated/entity-index.md (81 entities); scripts/generate_api_reference.py → docs/generated/api-reference.md
    (1748 endpoints from JAX-RS annotations). Byte-identical output; make generate-reference-docs.

  4. Harness-integrity CI (warnings-only) — scripts/harness/check_harness.py (6 checks: dead refs, AGENTS↔CLAUDE sync, skill symlinks, doc-size budgets, rule globs, generated-doc freshness) +
    .github/workflows/harness-integrity.yml. Intentionally non-blocking.

  5. AGENTS.md ↔ CLAUDE.md sync — AGENTS.md is now a git symlink to CLAUDE.md (was a drifting 255-line mirror).

  6. Enforcement hooks + skills — .claude/settings.json PreToolUse hooks block edits to generated output/workflows; .pre-commit-config.yaml + scripts/check-ui-*.sh; skills consolidated into a single
    skills/ source of truth (symlinked from .claude/skills, .agents/skills).

  7. Repo audit docs — docs/tech-debt.md, docs/quality.md, docs/golden-principles.md (evidence-cited). docs/harness-audit/ left intentionally untracked.

Verification

  • check_harness.py → only the two standing warnings, no new ones.
  • Generators byte-stable: make generate-reference-docs leaves git diff empty (across PYTHONHASHSEED 0/1/999).
  • CLAUDE.md = 169 lines (under 200); AGENTS.md resolves to identical content via the symlink.

TeddyCr and others added 30 commits July 24, 2026 11:38
…f truth

Move the 6 real SKILL.md dirs out of .claude/skills/ into skills/ and
replace them with relative ../../skills/<name> symlinks matching the
existing 12. Merge the diverged .claude and .agents copies of
java-checkstyle and ui-checkstyle into one source each, fixing:
- py_format is ruff, not black/isort/pycln (per ingestion/Makefile)
- ui-checkstyle is one checkstyle job with six gated steps, not three
  per-area jobs (per .github/workflows/ui-checkstyle.yml)
Add the missing pr-checklist and openmetadata-workflow symlinks. Point
.agents/skills/ at the same source via symlinks.

Location/duplication only; no skill substance changed except the two
checkstyle merges. Details in docs/harness-audit/03-consolidation.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reduce always-loaded CLAUDE.md from 591 to 136 lines. Move path- and
language-specific guidance into .claude/rules/*.md (paths: frontmatter,
loaded only when Claude reads matching files); point procedural sections
at existing skills instead of duplicating them.

Correct five stale claims against the code, each noted in-file with its
audit finding: Webpack->Vite, Python 3.10-3.11->>=3.10 (CI 3.10),
17->19 locale files, 'make generate' is root-only, and UI Checkstyle is
one job with six steps (not three jobs).

Full old->new line mapping in docs/harness-audit/01-decomposition.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rs, repo-wide format/license

.claude/settings.json: replace the 12 advisory/inert hooks with 3 PreToolUse
blockers — keep --no-verify; add generated-output protection (block edits to
committed/build generated trees, directing to the schema + make generate); add
.github/workflows/** edit protection (user authorizes via
CLAUDE_ALLOW_WORKFLOW_EDITS=1; the agent cannot self-authorize). Deleted advisory
hooks' guidance already lives in .claude/rules/*.

Format/license enforced repo-wide via .pre-commit-config.yaml for all contributors:
add ui-prettier + ui-license-header local hooks (Java and Python format were
already present). Java/Python license deferred (two licenses in-repo + many
headerless files). Activate with 'make install_test precommit_install' (added to
CLAUDE.md bootstrap).

Rationale + trigger/non-trigger test evidence in docs/harness-audit/04-enforcement.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…/quality

Committing the read-only audit deliverables and the actionable docs derived
from them:
- docs/harness-audit/{00-findings, 07-settings-scope, 08a-topology,
  08b-adherence, 08c-feedback-loops, 08d-hazards, 08e-promotion-list}.md
- docs/{tech-debt, golden-principles, quality}.md

golden-principles.md and 08e-promotion-list.md are drafts for human
ratification — the promotion list changes what blocks contributors' PRs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ons)

The harness-audit reports are working artifacts that won't ship, so the
path-scoped rules loaded into agent context must not link to them. Removed
the (Audit: docs/harness-audit/...) citations from component-library, i18n,
migrations, and schema-first; the underlying facts stay stated in place.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Untrack the harness-audit working documents (00-findings through
08e-promotion-list, plus 01-decomposition / 03-consolidation / 04-enforcement)
— scaffolding, not shipping docs. Files remain on disk (untracked). The derived
docs that stay (docs/tech-debt.md, golden-principles.md, quality.md) are untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ARCHITECTURE.md — bird's-eye view (API-request / ingestion-run / search-query
paths), a codemap of the 12 Maven modules + the ingestion tree, and the 5
invariants the code actually keeps (acyclic modules, connector ServiceSpec
contract, generated-is-a-sink, schema-first, migration append-only) with what
enforces each. Every claim traces to the module graph or a file path; the
connector-contract and schema-count figures were re-measured (94/95 = 98.9%,
904 schemas). CLAUDE.md gains one pointer line: ARCHITECTURE.md (system map)
vs DEVELOPER.md (how-to).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…reports)

tech-debt.md, golden-principles.md, quality.md no longer cite the working
harness-audit reports (which are untracked); the measured numbers and the
reproducing commands stay inline.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…eference)

Two generators under scripts/, each with a make target and gated as generated output:

- scripts/generate_entity_index.py -> docs/generated/entity-index.md
  81 first-class entities (schema + javaType/id discriminator), joined to their
  generated Java/Python/TS paths and REST resource class (EntityResource<T,R>).

- scripts/generate_api_reference.py -> docs/generated/api-reference.md
  1748 endpoints parsed from the 122 JAX-RS *Resource.java classes (method + path
  exact; purpose from @operation(summary) where present, never inferred). Source is
  the annotations, NOT openapi.yml (a 300-byte SwaggerBundle config stub).

Output is byte-identical across runs and hash seeds (sorted, no timestamps), so the
freshness CI job can fail on any drift. make targets: generate-entity-index,
generate-api-reference, generate-reference-docs. Both outputs are added to the
generated-output PreToolUse block in .claude/settings.json.

A third generator (db-schema) was intentionally NOT built: it cannot be produced
reliably from bootstrap/sql/schema/*.sql without adding a SQL parser + a
migration-replay engine + cross-dialect diffing. A reference wrong part of the time
is worse than none.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Indexes every knowledge doc under docs/ plus the reference docs that live in
other trees (openmetadata-ui/.../docs/{colors,formutils}.md, the Playwright
coverage docs, ingestion/docs/design/ingestion-diagnostics.md,
bootstrap/MIGRATION_SYSTEM.md). Each entry: path, one-line purpose, when an agent
should read it, git last-modified date, and a freshness verdict
(CURRENT/STALE/SUPERSEDED) verified against the working tree — one plan is
SUPERSEDED, several are CURRENT-with-caveat (footnoted). Moves nothing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
scripts/harness/check_harness.py runs six decay checks and emits GitHub warning
annotations (exit 0 unless --strict, so it never blocks a PR):
  1. dead references — a path/make target/yarn script/mvn goal named in CLAUDE.md,
     AGENTS.md, ARCHITECTURE.md, docs/index.md, .claude/rules/**, or a SKILL.md that
     no longer resolves (parses code spans only; anchored to real repo roots)
  2. AGENTS.md drift from CLAUDE.md's corrected stack facts
  3. skill symlink integrity (.claude/skills, .agents/skills) + same-name divergence
  4. doc-size budgets: CLAUDE.md <=200, ARCHITECTURE.md <=300, each rule <=100
  5. rule-glob: a .claude/rules paths: glob matching zero files
  6. docs/generated/** freshness (subsumes the reference-docs freshness check)

Runs via python3 scripts/harness/check_harness.py
::warning file=AGENTS.md,line=12::[agents-sync] AGENTS.md says 'Webpack'; the UI is built with Vite (mirror CLAUDE.md's 'Stack at a glance').
::warning file=.claude/rules/java.md,line=1::[doc-size] 144 lines exceeds rule budget of 100

=== harness-integrity summary ===

agents-sync (1):
  AGENTS.md:12  AGENTS.md says 'Webpack'; the UI is built with Vite (mirror CLAUDE.md's 'Stack at a glance').

doc-size (1):
  .claude/rules/java.md:1  144 lines exceeds rule budget of 100

total: 2 warning(s) locally and a single new root workflow (staged
separately; the workflow-edit guard blocks the agent from writing .github/workflows/).
NOT folded into skills/.github/workflows/lint-standards.yml — that is the skills
plugin's own CI (triggers on skills/**, not run by the monorepo) and can't reach
repo-root files. On the current tree it reports 2 genuine findings (AGENTS.md's
'Webpack', java.md at 144 lines) and zero false positives.

Also: ARCHITECTURE.md ingestion codemap rows now use the file's own '…' abbreviation
convention (they were abbreviated paths written as if literal); CLAUDE.md gains a
pointer-index note describing the checks.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
AGENTS.md is now generated from CLAUDE.md by scripts/harness/sync_agents_md.py, so
the two can no longer drift (this fixes AGENTS.md's Webpack/AntDesign/Flyway
contradictions — tech-debt open-metadata#6). Mechanism:
  - scripts/harness/sync_agents_md.py renders AGENTS.md = banner + CLAUDE.md body
  - make sync-agents-md regenerates it
  - harness-integrity check 2 now warns unless AGENTS.md == render(CLAUDE.md)
    (replaces the earlier Webpack-only drift heuristic)
  - .claude/settings.json blocks hand-edits to AGENTS.md and redirects to CLAUDE.md
  - CLAUDE.md pointer-index note updated to describe the sync

Harness check on the current tree: 1 warning (java.md 144 > 100 budget); AGENTS.md
sync now passes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
AGENTS.md is now a symlink to CLAUDE.md, so the two are literally the same file and
can never drift. Simpler than the generated mirror it replaces:
  - deleted scripts/harness/sync_agents_md.py and the make sync-agents-md target
  - harness-integrity check 2 now warns unless AGENTS.md is a symlink resolving to
    CLAUDE.md (ln -sf CLAUDE.md AGENTS.md)
  - .claude/settings.json block + CLAUDE.md note updated for the symlink mechanism

Harness check: 1 warning (java.md 144 > 100 budget); AGENTS symlink check passes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Runs scripts/harness/check_harness.py on PRs touching the agent-facing config
(CLAUDE.md, AGENTS.md, ARCHITECTURE.md, docs/**, .claude/rules/**, skills, Makefile,
generator sources). Emits GitHub warning annotations only; never fails a PR. Placed
with explicit user authorization for this one file.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The GoF patterns this codebase uses idiomatically, each with the canonical class to
copy the idiom from - so agents extend the established pattern instead of inventing a
parallel one. Grounded entirely in this repo (verified class/package citations),
covering Java (Template Method in EntityRepository, Factory/Registry via Entity +
SecretsManagerFactory, Strategy, Adapter in SearchClient, Facade in CollectionDAO,
Observer, Chain of Responsibility, Command, Visitor via ANTLR, cursor Iterator,
Proxy/Composite), Python ingestion (create() contract, ServiceSpec factory, dispatch
registries, entity adapters, singledispatch Strategy, generator Iterator,
Source->Sink pipeline), and the TS *ClassBase singleton seam.

Wired: added to the harness dead-reference check (REF_DOCS) so its ~40 code citations
stay verified; pointer added to CLAUDE.md's index (mirrored to AGENTS.md via symlink).
Harness check: 1 warning (java.md size); all citations resolve.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CLAUDE.md's header now instructs agents to consult docs/index.md (the knowledge
index) before writing new docs, so its 27 catalogued design/plan/reference docs are
reachable from the always-loaded entry point. Previously docs/index.md was only named
inside the dead-reference check's file list, not as a 'read this' pointer.
Mirrored to AGENTS.md via the symlink.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
'before writing new ones' was too narrow — docs/index.md is most useful during
ordinary coding (find the RDF / migration / auto-classification doc for the area you
touch), not only when authoring new docs. Reworded to 'for whatever area you're
working on'. Mirrored to AGENTS.md via symlink.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…stem' into MINOR-Machine-Readable-Design-System
Copilot AI review requested due to automatic review settings July 27, 2026 22:42

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot wasn't able to review this pull request because it exceeds the maximum number of files (300). Try reducing the number of changed files and requesting a review from Copilot again.

@github-actions github-actions Bot added safe to test Add this label to run secure Github workflows on PRs and removed safe to test Add this label to run secure Github workflows on PRs labels Jul 27, 2026
TeddyCr and others added 2 commits July 27, 2026 16:04
The gradient variant's border was migrated from the arbitrary hex
border-[#EFF8FF] to the tw:border-brand-50 token utility (#EFF8FF == brand-50);
assert the token class instead of the old arbitrary hex.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added safe to test Add this label to run secure Github workflows on PRs and removed safe to test Add this label to run secure Github workflows on PRs labels Jul 27, 2026
@gitar-bot

gitar-bot Bot commented Jul 27, 2026

Copy link
Copy Markdown
Code Review 👍 Approved with suggestions 0 resolved / 3 findings

Introduces an agentic-first context and harness-integrity system to structure agent guidance and validate documentation freshness. Consider addressing minor findings regarding unclosed file handles in check_harness.py, working tree mutation during generation checks, and silent failures in the freshness check.

💡 Bug: generated-fresh check silently passes if a generator fails

📄 scripts/harness/check_harness.py:440-453

check_generated_fresh runs each generator with subprocess.run(..., check=False) and then only inspects git diff on docs/generated. If a generator errors out (import error, exception, missing dep) it writes nothing, the diff is empty, and the freshness check reports clean — the exact opposite of its purpose. Since this is the integrity tool meant to catch doc drift, a crashing generator would go unnoticed. Capture the return code and emit a warning when a generator exits non-zero.

Warn when a generator exits non-zero so a crash isn't mistaken for 'fresh'.
for gen in generators:
    res = subprocess.run([sys.executable, rp(gen)], cwd=REPO,
                         stdout=subprocess.DEVNULL, stderr=subprocess.PIPE, text=True, check=False)
    if res.returncode != 0:
        warnings.append(Warn("generated-fresh", gen, 1,
                             f"generator failed (exit {res.returncode}); freshness unverified"))
💡 Quality: harness 'check' mutates the working tree as a side effect

📄 scripts/harness/check_harness.py:440-453

check_generated_fresh regenerates docs/generated on every invocation, so running make harness-check locally can leave uncommitted regenerated files behind — surprising for something named a 'check'. Consider regenerating into a temp dir and diffing, or restoring the tree afterward, so the check is read-only. Minor since the CI job is non-blocking, but it can confuse local runs and pollute an in-progress working tree.

💡 Quality: Unclosed file handles in check_harness.py helpers

📄 scripts/harness/check_harness.py:204-206 📄 scripts/harness/check_harness.py:371

maven_plugin_prefixes() and check_skill_symlinks() open files with bare open(...).read() without a context manager (lines 205 and 371), leaking file descriptors during the tree walk. Use with open(...) as fh: (or the existing read() helper) for consistency and to avoid ResourceWarnings. Low impact as this is a short-lived script, but trivially fixable.

🤖 Prompt for agents
Code Review: Introduces an agentic-first context and harness-integrity system to structure agent guidance and validate documentation freshness. Consider addressing minor findings regarding unclosed file handles in check_harness.py, working tree mutation during generation checks, and silent failures in the freshness check.

1. 💡 Bug: generated-fresh check silently passes if a generator fails
   Files: scripts/harness/check_harness.py:440-453

   check_generated_fresh runs each generator with subprocess.run(..., check=False) and then only inspects `git diff` on docs/generated. If a generator errors out (import error, exception, missing dep) it writes nothing, the diff is empty, and the freshness check reports clean — the exact opposite of its purpose. Since this is the integrity tool meant to catch doc drift, a crashing generator would go unnoticed. Capture the return code and emit a warning when a generator exits non-zero.

   Fix (Warn when a generator exits non-zero so a crash isn't mistaken for 'fresh'.):
   for gen in generators:
       res = subprocess.run([sys.executable, rp(gen)], cwd=REPO,
                            stdout=subprocess.DEVNULL, stderr=subprocess.PIPE, text=True, check=False)
       if res.returncode != 0:
           warnings.append(Warn("generated-fresh", gen, 1,
                                f"generator failed (exit {res.returncode}); freshness unverified"))

2. 💡 Quality: harness 'check' mutates the working tree as a side effect
   Files: scripts/harness/check_harness.py:440-453

   check_generated_fresh regenerates docs/generated on every invocation, so running `make harness-check` locally can leave uncommitted regenerated files behind — surprising for something named a 'check'. Consider regenerating into a temp dir and diffing, or restoring the tree afterward, so the check is read-only. Minor since the CI job is non-blocking, but it can confuse local runs and pollute an in-progress working tree.

3. 💡 Quality: Unclosed file handles in check_harness.py helpers
   Files: scripts/harness/check_harness.py:204-206, scripts/harness/check_harness.py:371

   maven_plugin_prefixes() and check_skill_symlinks() open files with bare open(...).read() without a context manager (lines 205 and 371), leaking file descriptors during the tree walk. Use `with open(...) as fh:` (or the existing read() helper) for consistency and to avoid ResourceWarnings. Low impact as this is a short-lived script, but trivially fixable.

Options

Display: compact → Showing less information.

Comment with these commands to change the behavior for this request:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar | Powered by Gitar — free for open source

@github-actions

Copy link
Copy Markdown
Contributor

Jest test Coverage

UI tests summary

Lines Statements Branches Functions
Coverage: 65%
65.67% (76800/116936) 49.54% (46114/93066) 50.76% (13892/27365)

@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Ingestion safe to test Add this label to run secure Github workflows on PRs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants