Skip to content

compliance(storyboards): drop sb=<doc.id> from contradiction lint env fingerprint (#2670 pt2)#2714

Merged
bokelley merged 2 commits into
mainfrom
bokelley/sb-removal-2670pt2
Apr 21, 2026
Merged

compliance(storyboards): drop sb=<doc.id> from contradiction lint env fingerprint (#2670 pt2)#2714
bokelley merged 2 commits into
mainfrom
bokelley/sb-removal-2670pt2

Conversation

@bokelley

Copy link
Copy Markdown
Contributor

Summary

Closes the #2670 planned evolution (part 2): removes sb=<doc.id> from the contradiction lint's env fingerprint so cross-storyboard contradictions actually surface. Builds on PR #2710 (#2684, role= forward guard) which was the prerequisite audit.

Why now

Including the storyboard id in the fingerprint was conservative-by-design during the lint's initial rollout (#2661) but suppressed the exact class of bug the lint was built to catch — #2627, #2628, #2629 all shared the shape "two locally-valid storyboards encoding disagreeing required responses for the same request." The richer env fingerprint is now sufficient:

  • #2679test_kit + top-level fixtures
  • PR #2710 (from #2684) — role=<doc.caller.role>
  • #2708 — tracks the auth= identity-vs-strategy gap (out of scope here)
  • #2711 — filed from protocol review on this PR; covers the transport-default auth inheritance hole that sb= removal exposes (out of scope, deferred)

Experiment result

On the current 56-storyboard suite, after removing sb=:

  • 10 multi-member groups form; 7 span ≥2 storyboard files
  • Biggest cross-file groups:
    • get_adcp_capabilities → success agreed across 25 files on acme-outdoor.yaml
    • get_adcp_capabilities → success agreed across 6 files on nova-motors.yaml
    • sync_accounts → success across 8 files; get_products pairs across scenarios; list_creative_formats across creative-generative + creative-template
  • Zero contradictions — suite is genuinely consistent, lint gains real cross-storyboard coverage

Changes

Expert review

Three rounds pre-push:

  • Code reviewer — ship it. Removal clean, inverted test triangulated well. Nit applied: changeset now notes the 6-file nova-motors group as a second cross-brand consistency win alongside the 25-file acme-outdoor one.
  • Testing expert — tightened the inverted test on three axes: assert via c.members (full group, stable) instead of c.mismatch (picked pair, brittle under group-size changes); added an outcome-pair sort assertion to pin the kind of disagreement not just its existence; added the complementary negative test they recommended; updated the test_kit discriminates env comment so a future reader doesn't delete it as redundant.
  • Ad-tech protocol expert — removal structurally sound. Time-dependent state, controller session affinity, branch-set peers, locale/currency all adequately covered by existing components. Flagged one real residual hole: fingerprintEnv gates its auth emission on if (step.auth) — steps inheriting the transport's default auth contribute nothing, so two storyboards with different transport defaults can collide. Filed as #2711 with a concrete resolve-then-emit proposal; out of scope for this PR since no storyboard in the current suite exercises the case.

Test plan

  • npm run test:storyboard-contradictions — 27/27 pass (1 inverted, 1 new)
  • npm run build:compliance — all four storyboard lints green, 56 storyboards build
  • npm run test:unit — 631/631 pass (precommit)
  • npm run typecheck — clean (precommit)
  • Manual experiment harness (.context/try-sb-removal.cjs) confirmed zero new contradictions + 7 cross-file groups before the source edit landed

🤖 Generated with Claude Code

… fingerprint (#2670 part 2)

Including the storyboard id was conservative-by-design during the
lint's initial rollout (#2661) but suppressed the exact class of bug
the lint was built to catch — cross-storyboard contradictions (#2627,
#2628, #2629). Prerequisites for the removal are now in place: #2679
added test_kit + top-level fixtures precision, PR #2710 (from #2684)
audited principal identity and added role= as the forward guard, and
#2708 tracks the remaining auth= structural gap.

Experiment on the current 56-storyboard suite: removing sb= surfaces
10 multi-member groups (7 spanning ≥2 files), including 25 files
agreeing that get_adcp_capabilities returns success on acme-outdoor
and 6 doing the same on nova-motors. Zero contradictions — the suite
is genuinely consistent and the lint now exercises cross-storyboard
checks as originally intended.

Inverts one test (no-contradiction-when-ids-differ → contradictions-
surface-when-ids-differ-but-env-matches) to pin the new behavior,
adds a complementary negative test (different test_kit + different
ids → no contradiction) to pin test_kit= as a cross-file separator
now that sb= is gone, and updates the `test_kit discriminates env`
comment to note test_kit= is its sole discriminator post-removal.

Protocol review surfaced a residual hole that sb= removal exposes:
steps inheriting the transport's default auth emit no auth= component,
so two storyboards with different transport defaults could collide.
Out of scope here; tracked as #2711.

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

Extracts auth emission into a describeStepAuth() helper that always
returns a stable token. Fixes two structural gaps that removing
sb=<doc.id> (#2670 part 2) exposed:

  #2711 — inherited-default steps (336 of 340 in the current suite)
    used to emit no auth= component, so they could collide silently
    with explicit steps authored against divergent transport
    defaults. Now emits auth=kit_default.

  #2708 — auth.from_test_kit was read as boolean regardless of
    whether it was true or a string path, collapsing distinct
    principals in multi-principal kits. Now emits
    auth=<type>:from_test_kit:<path> for string form. Literal
    auth.value is sha1-8hex hashed so different literals don't
    collide (defense-in-depth; #2720 tracks flagging literals as a
    code smell).

Zero grouping change on the current suite — no storyboard uses
string-form from_test_kit or literal value; all 336 inheriting
steps get the new kit_default token uniformly.

Tests:
  - describeStepAuth shape-matrix unit test, every branch including
    defensive fallbacks. Literal hashes pinned to precomputed sha1
    values for stability.
  - Inherited-default cross-storyboard test asserting kit_default
    emission and contradiction surface when outcomes disagree.
  - Multi-principal forward-guard test pinning that from_test_kit
    path selection discriminates, with direct fingerprintEnv
    comparison asserting the path token appears verbatim.

Protocol review surfaced one structural question deferred as
#2721: runner test kits (webhook-receiver, substitution-observer,
signed-requests) have no auth: block — if a storyboard ever
composes runner + primary kit, kit_default becomes ambiguous.
No storyboard does that today.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@bokelley bokelley merged commit b63b02b into main Apr 21, 2026
12 checks passed
@bokelley bokelley deleted the bokelley/sb-removal-2670pt2 branch April 21, 2026 21:18
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