Skip to content

fix(ci): pair gate resolves declared Pairs-with on an empty surface; record gate strips comments; chart freeze hardening - #7526

Merged
systemorph[bot] merged 3 commits into
mainfrom
fix/ci-gates-7397-7366-7391
Oct 29, 2026
Merged

systemorph[bot] merged 3 commits into
mainfrom
fix/ci-gates-7397-7366-7391

Conversation

@rbuergi

@rbuergi rbuergi commented Oct 29, 2026

Copy link
Copy Markdown
Contributor

Three CI gate scripts each passed a case they exist to catch. Each fix ships with self-test cases. Every new case fails against the previous logic (checked by mutating the fix back out) and passes now.

check-cross-repo-pair.py: a declared Pairs-with: is resolved even when no public surface left. The gate returned "no cross-repo pair to gate" before it parsed the body, so a dependency-only or pin-only removal held nothing even when it declared its counterpart (#7205, #7179). Now:

  • a Pairs-with: naming a pull request is resolved under the usual merged-into-default-branch verdict, whatever the detector found;
  • a malformed declaration fails;
  • Pairs-with: none — …, or no declaration, on an empty surface still passes.

Before the fix, 3 of 45 self-tests failed. After it, all 45 pass.

check-record-signatures.py: comments are no longer counted as parameters. // and /* */ are stripped before parameters are counted, on both sides of the comparison. String and char literals are kept verbatim, so a // inside "https://…" survives.

  • A census over src/ found 837 public records, and ONE parsed differently: NodeCompilationResult, which read as 10 parameters for its real 9. So the defect is live today, not latent.
  • New cases: the feat(onboarding): the first global administrator is pinned to no learning path #5077 shape, a reworded comment, a comment gaining a comma while a parameter leaves, a // inside a string default, and a commented-out record. With the strip removed, 3 fail.

check-chart-freeze.py: two gaps closed.

  • A non-deletion at a directory ABOVE a frozen path (deploy/aks replaced by a symlink) is now refused.
  • A saved --diff-file listing is read strictly: the whole status token must be valid, and every path field must be present and non-empty. Dgarbage and R100 with no destination used to pass.

Before the fix, 4 of 26 cases failed. After it, all 26 pass. --base origin/main is still clean.

Doc pages updated: Architecture/CrossRepoPairGate.md (the declaration section, and a new "Comments are not parameters" section) and Architecture/ChartOwnershipAndRunnerPool.md.

Not established, and not changed here: check-type-forwards.py (_positional_parameters) has the same comment blindness. On NodeCompilationResult it indexes two phantom members, Structured and table. That script is a subject of the parser-delta control, so a change to its counts needs its own declared pull request. It is filed for triage separately.

Pairs-with: none — CI scripts and docs only; no public C# surface, project path or package pin changes

Closes #7397
Closes #7366
Closes #7391

🤖 Generated with Claude Code

…; record gate strips comments; chart freeze refuses ancestors and malformed records

- check-cross-repo-pair.py: a declared `Pairs-with:` is resolved even when no public
  type, member or project path left (#7397); malformed declarations fail there too.
- check-record-signatures.py: strip // and /* */ comments before counting primary
  constructor parameters (#7366); census found one live mis-parse (NodeCompilationResult).
- check-chart-freeze.py: refuse a non-deletion at an ancestor of a frozen path, and
  validate the whole status token and the path fields of a saved listing (#7391).

Each new self-test case fails against the previous logic and passes now.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 29, 2026 06:32
@rbuergi
rbuergi enabled auto-merge (squash) October 29, 2026 06:32
@systemorph
systemorph Bot disabled auto-merge October 29, 2026 06:35

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.

🟡 Changes recommended

Unresolved scanner bugs can hide records and let constructor-arity changes pass undetected, while the chart-freeze checker also accepts invalid scored deletions.

3 open issues
What changed in this PR

This PR hardens three CI gates that protect cross-repository landing order, record constructor compatibility, and frozen deployment paths.

Changes:

  • Resolves declared Pairs-with: references even when no public-surface removal is detected.
  • Strips comments before parsing record signatures and adds regression cases.
  • Rejects replacements above frozen paths and strengthens saved-diff validation, with updated tests and documentation.
File Description
src/​MeshWeaver.Documentation/​Data/​Architecture/​CrossRepoPairGate.md Documents declaration enforcement and comment-aware record parsing.
src/​MeshWeaver.Documentation/​Data/​Architecture/​ChartOwnershipAndRunnerPool.md Explains ancestor protection and strict saved-diff validation.
scripts/​check-record-signatures.py Adds comment stripping and record-signature regression cases.
scripts/​check-cross-repo-pair.py Checks declared counterparts on empty removal reports.
scripts/​check-chart-freeze.py Adds ancestor checks, status validation, and regression cases.

Review effort: Balanced

Comment thread scripts/check-record-signatures.py Resolved
Comment thread scripts/check-record-signatures.py Resolved
Comment thread scripts/check-chart-freeze.py Resolved
rbuergi and others added 2 commits October 29, 2026 07:52
…reeze refuses scored deletions

A mis-bounded literal left text outside any string, where a '/*' opened a
phantom comment that hid every later record, so an arity change passed. A
raw literal now closes at its own quote count, and interpolation holes are
scanned as code. The chart-freeze status reader scores only C/R/M and caps
the score at 100, so D100 is refused instead of exempted as a deletion.
New self-test cases fail on the previous logic; the src census is unchanged.

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

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.

🟡 Changes recommended

Two interpolation-parsing defects can hide subsequent record declarations, allowing constructor-arity changes to pass undetected.

2 open issues
3 resolved since last review

Review effort: Balanced

Comment on lines +210 to +212
if c in "\"'":
j = _skip_literal(text, j)
continue

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Not changing this in round 3. It is a real lexer gap, but you only reach it with a block comment that holds a } INSIDE an interpolation hole and is followed by a literal /* in that same hole. That is far outside how this tree writes C#. Extending the hand lexer to cover comments in holes is hardening beyond this PR's scope, which is the comment stripping for ordinary code that #7366 asked for. I filed it to triage together with the raw-literal case on the sibling thread (rbuergi/Feedback/20261029-record-gate-lexer-comments-and-raw-literals-in-holes), with both repro shapes and a regression-case plan.

Comment on lines +245 to +247
if run >= 3 and not verbatim:
close = text.find('"' * run, i + run)
return n if close == -1 else close + run

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Same answer as the sibling thread. A raw interpolated string whose hole holds another raw literal that contains /* is valid C#, but nothing in this tree is written that way, and following raw-interpolation holes recursively (dollar count included) is a lexer extension rather than a fix to what this PR changes. It is in the same triage item as the comment-in-hole case: rbuergi/Feedback/20261029-record-gate-lexer-comments-and-raw-literals-in-holes.

@rbuergi
rbuergi enabled auto-merge (squash) October 29, 2026 06:58
@systemorph
systemorph Bot disabled auto-merge October 29, 2026 06:59
@github-actions

Copy link
Copy Markdown
Contributor

Test Results

    24 files      24 suites   56m 20s ⏱️
12 088 tests 12 086 ✅ 2 💤 0 ❌
12 114 runs  12 112 ✅ 2 💤 0 ❌

Results for commit 4e072a2.

@systemorph
systemorph Bot enabled auto-merge October 29, 2026 07:17
@systemorph
systemorph Bot merged commit 09c5bbf into main Oct 29, 2026
69 of 77 checks passed
@rbuergi
rbuergi deleted the fix/ci-gates-7397-7366-7391 branch October 31, 2026 09:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants