Skip to content

fix(controlplane): compare contracts semantically for change detection#3233

Draft
javirln wants to merge 1 commit into
chainloop-dev:mainfrom
javirln:dry-run-contract
Draft

fix(controlplane): compare contracts semantically for change detection#3233
javirln wants to merge 1 commit into
chainloop-dev:mainfrom
javirln:dry-run-contract

Conversation

@javirln

@javirln javirln commented Jun 23, 2026

Copy link
Copy Markdown
Member

Description

Contract change-detection compared raw bytes, so re-applying the same contract through different client paths produced spurious revisions and false drift on dry-run apply. The verbatim wf contract apply path sends the on-disk bytes, while the batch apply path (including --dry-run) re-marshals the YAML, re-indenting it. Because the stored bytes never matched the reindented incoming bytes, every drift check reported the contract as changed.

The server comparison is now semantic instead of raw-byte. A new biz.ContractRawEqual helper parses both the stored and incoming bodies (reusing the existing unmarshal/validate path) and compares their canonical proto form, so formatting-only differences (indentation, key order, YAML vs JSON) no longer register as changes. Both the real-apply revision decision and RevisionWouldChange use it. Stored raw bodies are unchanged and still served back to clients verbatim; only the equality check changes.

Re-applying the same contract via any path now reports "unchanged", a genuine content edit is still detected as a change, and applying the same contract twice remains idempotent.

Closes PFM-6465

AI disclosure

Claude Code assisted in producing this change.

Review in cubic

Contract change-detection compared raw bytes, so re-applying the same
contract through different client paths (verbatim `wf contract apply` vs
the batch `apply` splitter, which re-marshals YAML) produced spurious
revisions and false dry-run drift. The comparison now parses both the
stored and incoming bodies and compares their canonical proto form,
making it insensitive to serialization/formatting differences while
still detecting genuine content changes. Stored raw bodies are unchanged
and still served back verbatim.

Assisted-by: Claude Code
Signed-off-by: Javier Rodriguez <javier@chainloop.dev>

Chainloop-Trace-Sessions: 606de1a5-e4ab-480b-8009-722416f5e18d
@chainloop-platform

chainloop-platform Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

AI Session Analysis

Avg score Sessions Failing policies Attribution Files Lines Total Duration
🟡 60% 1 ✅ 0 100% AI / 0% Human 4 +196 / -6 1h53m11s

🟡 60% — 100% AI — ✅ All policies passing

Jun 23, 2026 08:05 UTC · 1h53m11s · $21.24 · 87.3k in / 101.7k out · claude-code 2.1.186 (claude-opus-4-8)

View session details ↗

Change Summary

  • Adds semantic contract comparison in controlplane change-detection paths.
  • Adds unit and integration coverage for formatting-insensitive equality.
  • Verifies unchanged and real-change cases against the running local stack.

AI Session Overall Score

🟡 60% — Strong fix, but the unfulfilled PR-opening request keeps alignment red.

AI Session Analysis Breakdown

🟢 96% · verification

🟢 AI proved the regression test fails under bytes.Equal and passes with semantic comparison. · High Impact

🟢 AI validated both unchanged and genuinely changed contracts against the running stack. · High Impact

🟢 94% · solution-quality

No notes.

🟢 92% · scope-discipline

No notes.

🟢 90% · context-and-planning

🟢 User front-loaded root cause, preferred fix, constraints, and live verification steps. · High Impact

🟢 88% · user-trust-signal

No notes.

🔴 35% · alignment

🔴 After promising an upstream PR, the session ended after commit-signature verification with no push or PR command. · High Severity

💡 Before declaring a workflow sequence complete, verify the last requested action happened; if blocked, say so explicitly instead of stopping mid-plan.


File Attribution

████████████████████ 100% AI / 0% Human

Status Attribution File Lines
modified ai app/controlplane/pkg/biz/workflowcontract_test.go +122 / -1
modified ai app/controlplane/pkg/biz/workflowcontract.go +46 / -2
modified ai app/controlplane/pkg/biz/workflowcontract_integration_test.go +23 / -0
modified ai app/controlplane/pkg/data/workflowcontract.go +5 / -3

Policies (4)

Status Policy Material Messages
✅ Passed ai-config-ai-agents-allowed ai-coding-session-606de1 -
✅ Passed ai-config-no-dangerous-commands ai-coding-session-606de1 -
✅ Passed ai-config-no-secrets ai-coding-session-606de1 -
✅ Passed ai-config-mcp-servers-allowed ai-coding-session-606de1 -

Powered by Chainloop and Chainloop Trace

@cubic-dev-ai cubic-dev-ai 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.

No issues found across 4 files

Re-trigger cubic

@migmartri migmartri left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't know, this looks strange, shouldn't we take a look at why different clients produce different outputs? at the end, we have the raw content.

Also, does this mean that if I add a comment now in the yaml it will not be saved because the marshalled output is the same?

@javirln javirln marked this pull request as draft June 24, 2026 14:28
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.

2 participants