Skip to content

docs(seam): delete the false FLUID alignment claim; gate the vendored copies - #6

Merged
fas89 merged 1 commit into
mainfrom
docs/honest-fluid-seam
Sep 7, 2026
Merged

fas89 merged 1 commit into
mainfrom
docs/honest-fluid-seam

Conversation

@fas89

@fas89 fas89 commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

FLUX claimed — in docs/reconciliation.md and in the published schema's own $defs/agentPolicy description — that its agent-policy vocabulary was "aligned with FLUID's" and that "seam-crossing policy comparison is field-to-field".

Neither is true.

Measured against fluid-schema-0.7.5.json

FLUX agentPolicy FLUID exposes[].policy.agentPolicy
members 5 13
token budget tokenBudget (integer) maxTokensPerRequest + maxTokensPerDay
purposeLimitation boolean string
use-case values free strings (minLength: 1) 12-value enum
FLUID-only — deniedModels, canReason, canStore, retentionPolicy, auditRequired, tags, labels

Three members line up by name and type: allowedModels, allowedUseCases, deniedUseCases.

The use-case row is the one that bites

FLUX accepts any non-empty string; FLUID accepts twelve specific values. So a ConsentProfile can deny a use case that no FLUID contract is able to express, and the "at least as strict" seam rule then has nothing to bind against on the FLUID side.

That is not hypothetical. Of the eleven distinct use-case values in FLUX's own 34 enforcement vectors — advertising, persona_variation, journey_synthesis, pricing_optimisation, exfiltrate-pii and the rest — none can be written into a FLUID contract. The comparison the old wording described has never had a working example in this repository's own test suite.

What the validator does enforce is real and still regression-tested: within FLUX, a simulation's declared policy is checked against its gating profile. The claim that this reached across the seam was the false part.

What changed

  • docs/reconciliation.md now carries the divergence table above, says plainly what does and does not cross the seam, and records two ways to resolve it — FLUX $refs FLUID's published agentPolicy $id (cleanest, breaking, cheapest now while FLUX has no external implementers), or FLUX keeps its own vocabulary and the table stands as the permanent honest statement. That is an open decision, recorded as one rather than pre-empted.
  • The same false sentence is removed from $defs/agentPolicy's description in flux-schema-0.5.0.json and the latest alias, with the mirror under flux_spec/data/ regenerated by scripts/sync-package-data.py.

Fixed in place rather than deferred to a version bump: 0.5.0 is untagged and flux-spec is not on PyPI (404). Publishing first would have shipped a citable falsehood to a package index.

Also: a gate for the vendored FLUID schemas

.github/workflows/fluid-vendor-sync.yml compares vendor/fluid/*.json against what FLUID publishes.

Correction to an earlier internal assessment: those copies are not drifted. I checked all three (0.7.3, 0.7.4, 0.7.5) canonically and they are byte-identical to the published schemas. The gap was never drift — it was that nothing enforced the absence of drift, and an unguarded cache ages. The job mirrors FLUID's own schema-sync.yml, compares canonical JSON so formatting churn can't fail the build, and runs weekly because FLUID can publish without FLUX touching anything.

The rule behind both halves of this PR: a cross-boundary claim is only true if the CI of the side making the claim proves it.

Tested

FLUX's own checks, with jsonschema, pyyaml and rfc8785 installed:

scripts/validate.py         exit 0
tests/test_regression.py    ok — 132 regression checks green
sync-package-data.py        mirror regenerated
latest alias                still byte-identical to 0.5.0

(Note for anyone reproducing: without rfc8785 installed, validate.py and the regression suite both exit 1 with a dependency message on a clean checkout — that failure is environmental, not a regression.)

🤖 Generated with Claude Code

… copies

FLUX claimed, in docs/reconciliation.md and in the published schema's own
$defs/agentPolicy description, that its agent-policy vocabulary was "aligned
with FLUID's" and that "seam-crossing policy comparison is field-to-field".
Neither is true.

Measured against fluid-schema-0.7.5.json:

  members              FLUX 5                    FLUID 13
  token budget         tokenBudget (integer)     maxTokensPerRequest +
                                                 maxTokensPerDay
  purposeLimitation    boolean                   string
  use-case values      free strings              12-value enum
  FLUID-only           --                        deniedModels, canReason,
                                                 canStore, retentionPolicy,
                                                 auditRequired, tags, labels

Three members line up by name and type: allowedModels, allowedUseCases,
deniedUseCases.

The use-case row is the one that bites. FLUX accepts any non-empty string;
FLUID accepts twelve specific values. So a ConsentProfile can deny a use case
no FLUID contract is able to express, and the "at least as strict" seam rule
then has nothing to bind against on the FLUID side.

That is not hypothetical. Of the eleven distinct use-case values in FLUX's own
34 enforcement vectors -- advertising, persona_variation, journey_synthesis,
pricing_optimisation, exfiltrate-pii and the rest -- NONE can be written into a
FLUID contract. The comparison the old wording described has never had a
working example in this repository's test suite.

What the validator does enforce is still real and still regression-tested:
within FLUX, a simulation's declared policy is checked against its gating
profile. The claim that this reached across the seam was the false part, and
docs/reconciliation.md now carries a divergence table saying exactly what does
and does not cross, plus the two ways to resolve it (FLUX $refs FLUID's
published agentPolicy $id, or keeps its own vocabulary and the table stands).
That is an open decision, recorded as one rather than pre-empted.

Fixed in place rather than deferred to a version bump: 0.5.0 is untagged and
flux-spec is not on PyPI, so nothing has shipped this text to a package index
yet. Publishing first would have made it a citable falsehood.

Also adds .github/workflows/fluid-vendor-sync.yml. The vendored FLUID schemas
under vendor/fluid/ are byte-identical to the published ones today -- I checked
all three canonically before writing this -- but nothing enforced that, and an
unguarded cache drifts. It mirrors FLUID's own schema-sync.yml, compares
canonical JSON so formatting churn cannot fail the build, and runs weekly
because FLUID can publish without FLUX touching anything.

The rule behind both halves: a cross-boundary claim is only true if the CI of
the side making the claim proves it.

Verified with FLUX's own checks (jsonschema, pyyaml, rfc8785): validate.py
exit 0, regression suite 132/132 green, package-data mirror regenerated via
scripts/sync-package-data.py, latest alias still identical to 0.5.0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@fas89
fas89 merged commit 0fb14f4 into main Sep 7, 2026
7 checks passed
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