Skip to content

v0.5.0 I4 slice 1: decision and canonical foundation - #228

Merged
michaelegner merged 2 commits into
mainfrom
i4-slice-1-decision-foundation
Sep 23, 2026
Merged

michaelegner merged 2 commits into
mainfrom
i4-slice-1-decision-foundation

Conversation

@michaelegner

Copy link
Copy Markdown
Owner

Summary

Implements I4 Draft 0.3 §15 Slice 1 — Decision and canonical foundation, the first I4 slice.

  • Decision: GO. The independent evidence record is docs/specifications/0.5.0/i4-decision-evidence.md. It uses seven sources retrieved 2026-09-23: Azure Service Bus, Google Pub/Sub, the OpenTelemetry messaging registry and spans, and Kafka Design. It maps each §4 distinction to a source, gives the §4.2 GO disposition, and records a disposition for every §19 checklist item.
  • ADR 0017 has status Proposed and moves to Accepted in slice 6. It supersedes ADR 0013 only for the Topic/Subscription prohibition and keeps both guards. The ADR 0013 status line and the ADR index are updated.
  • Canonical foundation. This adds no adapter behavior and persists no Pub/Sub node or relation (§11):
    • Topic and Subscription models with exactly the §6.2 fields. They are not yet on ArchitectureModel.
    • topic_owned_id and subscription_owned_id (§7.1/§7.2). The Subscription key binds the Topic id and has no consumer-group input.
    • The three §8.4 DiagnosticCode members, as vocabulary only.
    • Topic/Subscription uniqueness constraints.
  • Public contract skeleton (§12.1/§12.2):
    • EntityType.TOPIC|SUBSCRIPTION, EvidenceRelationType.PUBLISHES_TO|SUBSCRIPTION_OF and DeliveryRelationType.PUBLISHES_TO.
    • EntityRef protocol/namespace are allowed for QUEUE/TOPIC/SUBSCRIPTION.
    • DeliveryRef.subscription is optional: it must be null unless via is a Topic, and must be SUBSCRIPTION-typed when set.
    • Every rule is mirrored in the three regenerated v0.5 schemas. schema_version stays 0.5.
  • Persistence guard. A fail-closed test pins that importer NODE_LABELS/KNOWN_RELATION_TYPES, graph_schema RELATIONS, ArchitectureModel and _CANONICALIZATION_VERSION == 2 all still exclude Pub/Sub. Slice 2 opens that path atomically.

Test plan

  • uv run ruff format --check . / uv run ruff check .: clean
  • uv run python -m app.architecture_intelligence.schema_export: regeneration is idempotent (no diff on rerun)
  • uv run pytest tests/unit: 1955 passed (140 new)
  • uv run pytest tests/integration: 405 passed
  • Each of the six new/rewritten DeliveryRef schema rules is load-bearing. Deleting any one makes the exhaustive Pydantic⇔schema cross-product diverge on 2–8 cases.
  • No answer fixture or expected-answer file changed, so every existing claim id is byte-identical.

Reconciliation against the approved plan

Completed As Planned

Plan items 1–9: the evidence record, ADR 0017, the ADR 0013/README bookkeeping, the canonical models, the identity helpers, the DiagnosticCodes, the constraints, the public contract skeleton, and the schema regeneration. All acceptance tests are present:

  • identity golden vectors, prefix separation, and signature pinning;
  • the exact model field set;
  • the fail-closed persistence guard;
  • the exactly-three DiagnosticCode addition;
  • constraints in the unit test and the integration SHOW CONSTRAINTS check;
  • the exhaustive DeliveryRef and EntityRef Pydantic⇔schema parity checks;
  • the evidence-schema relation enum delta.

Deviations & Justification

  • Item 10, the fixture churn, was not needed. The i1/i2/i3 answer fixtures and scenario expected_answer.json files already omit null-valued optional fields: OPERATION refs carry no protocol key, for example. The loader reads them through model_validate. Adding "subscription": null would have broken that established style for no semantic gain. Live output does emit subscription: null, as pinned by test_delivery_ref_subscription_defaults_to_null_and_is_emitted. No fixture changed, so claim ids are trivially unchanged.
  • The EvidenceRelationType docstring was updated. It said "the 7 canonical graph relation kinds … (only CALLS/SENDS)", which was already stale after I3 and wrong after I4. The docstring appears in the evidence schema's description.

Specification Questions Discovered

  • For slice 2: widening _compute_mapping_context_digest with Topic/Subscription mapping keys would change every pre-I4 mapping-context digest, even with empty arrays. §7.3 requires the digest to cover the new arrays but does not say whether pre-I4 digests must stay stable. This is not decided here.

Deferred Work

This matches the plan's non-goals:

  • Slice 2: AsyncAPI mapping, the topicMappings/subscriptionMappings artifact, the persistence path and canonicalization v3, and the dead-letter carrier.
  • Slice 3: runtime.
  • Slice 4: the claim-id subscription_id and projection.
  • Slice 5: fixtures.
  • Slice 6: docs and the completion record.

Test/Qualification Evidence

Unit: 1955 passed. Integration: 405 passed. Ruff format and check: clean. Schema regeneration: idempotent.

Remaining Limitations

  • Several existing contract "fails both" tests pass without testing anything. Examples are test_claim_with_invalid_delivery_pair_fails_both_pydantic_and_schema and its neighbours. _answer_dict_with_claim_dict doesn't fill in the I3 deployment_claim_ids/deployment_resolutions, so every payload is invalid for that reason alone. The new I4 tests use a complete answer and have a positive control. The existing tests are unchanged here and are worth a separate small fix.
  • Kafka share groups are listed as out of scope from general knowledge, not a retrieved source, and the record says so.

Approved plan (persisted verbatim per this repo's specification-driven-implementation workflow)

I4 Slice 1 — Decision and Canonical Foundation

Planning started at 2026-09-23T16:26:49Z. The PR body must carry
<!-- aip-agent-metadata:v1 {"planning_started_at":"2026-09-23T16:26:49Z"} -->.

Context

I3 is complete (#225). The I4 specification merged in #226/#227 (f98e48b) as a GO candidate. It
states that implementation is not authorized until it and ADR 0017 are reviewed, and that ADR 0013
stays authoritative until then. Slice 1 (§15) is where that decision gets made: the evidence record,
ADR 0017, and the GO decision. With GO, the slice also adds the in-memory canonical foundation:
models, identity helpers, graph constraints and the public contract skeleton. It adds no adapter
behavior and persists no Pub/Sub node or relation
(§11, §15).

Decisions settled with the user:

  • GO. ADR 0017 is Proposed and becomes Accepted in slice 6. ADR 0013 is marked as superseded
    in part.
  • The evidence record is a separate file: docs/specifications/0.5.0/i4-decision-evidence.md.
  • Graph schema covers uniqueness constraints only. The Pub/Sub persistence and NL-query paths
    stay closed, and a test pins that.

Governing Specification

docs/specifications/0.5.0/i4-source-independent-pubsub-semantics.md, Draft 0.3, as merged at
f98e48b (#226 plus #227 residuals). Applicable sections: §4, §5, §6.2–6.3, §7.1–7.2, §8.4, §11,
§12.1–12.2, §12.6, §15 Slice 1, §16, §19.

The parent spec is docs/specifications/0.5.0/specification.md Part III (§§776–838). ROADMAP I4
row: "Recorded GO or DEFER".

Scope & Non-Goals

In scope

  1. Evidence record, docs/specifications/0.5.0/i4-decision-evidence.md. It contains:
    • Source URLs with retrieval date 2026-09-23 and short quoted passages for Azure Service Bus
      (queues are competing-consumer; each subscription gets a copy; consumers compete within a
      subscription), GCP Pub/Sub (fan-out across subscriptions; load-balancing within one), the OTel
      messaging registry (messaging.destination.subscription.name and
      messaging.consumer.group.name are distinct attributes, both Development stability), and
      Kafka (consumer groups).
    • Each §4 distinction mapped to its supporting source.
    • The §4.2 GO condition disposition.
    • A disposition for every item on the §19 entry-gate checklist. Each item is either satisfied by
      the spec text or deferred to a named later slice.
    • A statement that neither positive fixture needs a broker-specific exception.
  2. ADR 0017, docs/adr/0017-source-independent-pubsub-semantics.md, Status Proposed. It
    covers every §5 bullet:
    • records GO and cites the spec and evidence record;
    • supersedes only ADR 0013's Topic/Subscription prohibition;
    • retains both guards and names their entry points (app/telemetry/messaging_guards.py
      decide_destination_semantics and decide_service_identity) and their regression tests;
    • prohibits generic Destination normalization, consumer-group-to-Subscription equivalence, and
      runtime-only minting;
    • adds no MCP tool and no broker adapter;
    • cites ADR 0013 decision Add a Troubleshooting section to docs/development.md #2 and the bounded two-key OTel widening from §9.
  3. ADR bookkeeping:
    • docs/adr/0013-*.md: the status line gains "Superseded in part by 0017 (Topic/Subscription
      prohibition only; both guards retained)". The body is unchanged.
    • docs/adr/README.md: add a row for 0017 and a one-line provenance note.
  4. Canonical models, app/canonical/model.py: add Topic and Subscription with exactly the
    §6.2 fields id, name, protocol: str | None, namespace: str | None. There is no
    queue_type, no topic back-reference (that is carried only by SUBSCRIPTION_OF), and no
    consumer, group, partition or filter fields. They are not added to ArchitectureModel.
  5. Identity helpers, app/sources/owner_ids.py. Both mirror queue_owned_id (L123-144): pure
    hash formulas, keyword-only arguments, and the caller applies NFC, as the Queue docstring
    documents. Both reuse length_delimited and sha256_hex from app/sources/encoding.py.
    • topic_owned_id(*, stable_broker_id, normalized_namespace_or_empty, exact_topic_address)
      returns topic:owned:<sha256> (§7.1).
    • subscription_owned_id(*, stable_broker_id, normalized_namespace_or_empty, topic_id, exact_subscription_name) returns subscription:owned:<sha256> (§7.2), with the Topic id
      bound into the key.
  6. Diagnostic vocabulary, app/sources/model.py DiagnosticCode: add exactly
    TOPIC_IDENTITY_CONFLICT, SUBSCRIPTION_IDENTITY_CONFLICT and SUBSCRIPTION_IDENTITY_MISSING
    (§8.4). They are defined but not emitted yet.
  7. Graph constraints, app/graph/schema.py CONSTRAINTS: add
    topic_id / (t:Topic) REQUIRE t.id IS UNIQUE and subscription_id /
    (s:Subscription) REQUIRE s.id IS UNIQUE, in the existing pattern. This is a DB-level invariant
    only; no nodes are written.
  8. Public contract skeleton, app/architecture_intelligence/contracts.py. Every runtime rule
    has a json_schema_extra mirror.
    • EntityType: add TOPIC, SUBSCRIPTION.
    • EvidenceRelationType: add exactly PUBLISHES_TO, SUBSCRIPTION_OF (§12.1).
    • DeliveryRelationType: add PUBLISHES_TO.
    • EntityRef: protocol/namespace are allowed for QUEUE | TOPIC | SUBSCRIPTION. Update the
      runtime validator, and change the schema if const QUEUE to if enum [...].
    • _ALLOWED_DELIVERY_PAIRS: add (ASYNC_MESSAGE, PUBLISHES_TO, TOPIC).
    • DeliveryRef.subscription: EntityRef | None = None, emitted as null like the existing
      optional EntityRef fields. Invariants (§12.2):
      • subscription must be null unless via.type == TOPIC;
      • a non-null subscription must have type == SUBSCRIPTION.
    • Rewrite the schema mirror so ASYNC_MESSAGE admits SENDS/QUEUE or PUBLISHES_TO/TOPIC,
      and add the subscription rules as if/then.
    • The "SUBSCRIPTION_OF the via Topic in the same snapshot" rule (§12.2) needs a graph read. It
      is a projection invariant for slice 4, not a model rule.
  9. Schemas: regenerate the three schemas/architecture_intelligence/v0.5/*.schema.json files
    with uv run python -m app.architecture_intelligence.schema_export. schema_version stays
    "0.5".
  10. Fixture churn from the new always-emitted delivery.subscription: null:
    • update tests/fixtures/architecture_intelligence/{i1,i2,i3}/*.json and
      evaluation/architecture_answers/scenarios/*/expected_answer.json;
    • claim ids stay byte-identical, because the payload is unchanged in this slice;
    • verify that the only diff in those files is the added "subscription": null lines.

Non-goals, deferred to the named slice

  • AsyncAPI mapping, x-aip-destination-kind: topic, and topicMappings/subscriptionMappings
    artifact widening, including validator, index, resolver and mapping_context_digest: slice 2.
  • ArchitectureModel.topics/subscriptions, importer NODE_LABELS/KNOWN_RELATION_TYPES,
    graph_schema/registry.py RELATIONS, canonical validation, dedicated Topic/Subscription
    canonicalization queries, and the _CANONICALIZATION_VERSION 2→3 bump: slice 2, atomically.
  • The SubscriptionDeadLetterConfiguration carrier: slice 2.
  • All runtime/OTel changes: slice 3.
  • The claim-id subscription_id optional payload field, in both dependency_projection.py and
    evaluation/architecture_answers/reference/identities.py, plus the dependency/drift projection
    and evidence resolution: slice 4.
  • Broker fixtures and the full matrix: slice 5. Docs and the completion record: slice 6.
  • Not changed in this slice: the spec text itself, docs/canonical-model.md and
    docs/graph-model.md (slice 6), and MCP tools.

Affected Components

  • Docs:
    • docs/specifications/0.5.0/i4-decision-evidence.md (new)
    • docs/adr/0017-source-independent-pubsub-semantics.md (new)
    • docs/adr/0013-no-topic-family-without-guards.md (status line only)
    • docs/adr/README.md
  • Code:
    • app/canonical/model.py
    • app/sources/owner_ids.py
    • app/sources/model.py
    • app/graph/schema.py
    • app/architecture_intelligence/contracts.py
  • Generated: the 3 v0.5 schemas.
  • Fixtures: i1/i2/i3 answer fixtures and scenario expected_answer.json files (subscription
    null only).
  • Tests:
    • tests/unit/test_architecture_intelligence_contracts.py
    • tests/unit/test_sources_owner_ids.py
    • tests/unit/test_sources_model.py
    • a new tests/unit/test_canonical_pubsub_foundation.py
    • probably the schema-path-independent integration equivalence tests, if their golden outputs
      embed the delivery shape

Requirement -> Task Mapping

Spec requirement Task
§4, §4.1, §4.2 evidence and GO condition; §19 checklist Evidence record (1)
§5 ADR 0017 bullets; §9 cite ADR 0013 #2 ADR 0017 (2), 0013 status and README (3)
§6.2 Topic/Subscription fields; no consumer/group/partition/filter fields Canonical models (4)
§7.1 Topic owner key; §7.2 Subscription key binds Topic id; distinct prefixes Identity helpers (5)
§8.4 exactly three new DiagnosticCodes (6)
§11 "graph schema"; Slice 1 persists nothing Constraints (7); fail-closed persistence path
§12.1 EntityType, EvidenceRelationType additions; EntityRef protocol/namespace for Q/T/S (8)
§12.2 DeliveryRelationType.PUBLISHES_TO; DeliveryRef.subscription invariants (8)
§12.4 existing claim ids byte-identical Fixture churn check (10)
§12.6 all three schemas widened; unchanged portions compatible; version 0.5 (9)
§2, §12 exactly three MCP tools Unchanged; existing tool-count tests

Acceptance Criteria -> Test/Evidence Mapping

  • Identity helpers, in test_sources_owner_ids.py:

    • Golden vectors are computed independently in the test with hashlib and manual 8-byte
      big-endian length prefixes, not by calling length_delimited.
    • Topic id ≠ Queue id for the same broker, namespace and address.
    • The same Subscription name under two Topic ids gives distinct ids.
    • Broker, namespace and address each change the id.
    • Prefixes are topic:owned: and subscription:owned:.
    • There is no consumer-group parameter, asserted by signature inspection.
  • Canonical models: the field set is exactly {id, name, protocol, namespace}. Topic and
    Subscription are not in ArchitectureModel.model_fields.

  • Fail-closed persistence guard (new test):

    • PUBLISHES_TO and SUBSCRIPTION_OF are not in KNOWN_RELATION_TYPES or RELATIONS.
    • Topic and Subscription are not in NODE_LABELS values.
    • _CANONICALIZATION_VERSION == 2.
    • The test's docstring says slice 2 flips these atomically.
  • DiagnosticCode: the current membership minus a literal pre-I4 set equals exactly the three §8.4
    members.

  • Constraints: unit assertion that both Cypher strings are in CONSTRAINTS. The integration test
    test_ensure_schema_creates_constraints covers them against real Neo4j (a subset check, so add
    both names).

  • Contract, Pydantic ⇔ schema parity. An exhaustive parametrized cross-product over:

    • kind × relation_type × via.type (all 6 non-WORKLOAD types);
    • subscription ∈ {null, SUBSCRIPTION ref, QUEUE-typed ref, TOPIC-typed ref}.

    For each combination, Pydantic acceptance must equal jsonschema acceptance against the committed
    schema. Exactly these are valid:

    • SYNC_HTTP/CALLS/OPERATION with null subscription;
    • ASYNC_MESSAGE/SENDS/QUEUE with null subscription;
    • ASYNC_MESSAGE/PUBLISHES_TO/TOPIC with null or a SUBSCRIPTION ref.

    EntityRef protocol/namespace parity runs across all types. Evidence schema enum membership
    includes the two new relation types.

  • Schema frozen parity: the existing byte-equality tests pass after regeneration, and a rerun
    is idempotent.

  • Queue non-regression:

    • The existing contract, projection and equivalence suites pass.
    • Claim ids in all fixtures are unchanged. The fixture diff check is
      git diff -U0 -- tests/fixtures evaluation | grep '^[-+] ' | grep -v subscription must be
      empty apart from headers.
  • MCP: tool count is still 3 (existing tests).

Validation Commands

  1. uv run ruff format ., then uv run ruff check --fix ., before any test run.
  2. uv run python -m app.architecture_intelligence.schema_export, run twice to confirm the output
    is idempotent.
  3. uv run pytest tests/unit
  4. uv run pytest tests/integration (real Neo4j)
  5. uv run ruff check . and uv run ruff format --check .
  6. Run the fixture-diff check above, and git diff --stat for scope review.

Open Questions / Assumptions / Stop Conditions

  • Assumption: the three DiagnosticCodes land in slice 1 as vocabulary, defined but not emitted.
    §13.1's "exactly three" check is pinned now.
  • Assumption: DeliveryRef.subscription is always emitted as null, matching the EntityRef
    optional-field pattern and spec §12.2's EntityRef | null. This causes fixture churn but no
    claim-id change.
  • Assumption: DependencyClaim needs no new object-type rule. The existing rule allows TOPIC
    and SUBSCRIPTION objects, as §12.3's DIRECT_TARGET_FALLBACK requires.
  • Forward flag for slice 2, not decided here: widening _compute_mapping_context_digest with
    new sharedTopicMappings/sharedSubscriptionMappings keys would change every existing
    mapping-context digest even when the arrays are empty. §7.3 requires the digest to cover the new
    arrays, but it doesn't say whether pre-I4 digests must stay stable. Slice 2 planning must raise
    this.
  • Stop:
    • If the Kafka documentation contradicts "consumer group ≠ stable named broker Subscription", stop
      and return to §4 (a DEFER risk).
    • If any existing claim id changes, stop.
    • If widening the contract needs a WORKLOAD branch or a fourth tool, stop.
    • If any test requires persisting Pub/Sub state, stop.
    • Any §16 item is a stop.
  • Workflow:
    • Branch from a freshly synced main, named i4-slice-1-decision-foundation.
    • Persist this plan verbatim in the PR body with the telemetry marker.
    • No commit or PR without an explicit request. Never merge.

🤖 Generated with Claude Code

Record the I4 Pub/Sub gate outcome as GO (spec §4, §15 Slice 1):
- docs/specifications/0.5.0/i4-decision-evidence.md: independent evidence
  record (ASB, GCP Pub/Sub, OTel, Kafka; retrieved 2026-09-23), §4
  distinction mapping, §4.2 GO disposition, §19 checklist dispositions.
- ADR 0017 (Proposed): supersedes ADR 0013 only for the Topic/Subscription
  prohibition; both guards retained. ADR 0013 status and index updated.

Add the in-memory canonical foundation (no adapter behavior, no persisted
Pub/Sub node or relation, spec §11):
- canonical Topic/Subscription models (not yet on ArchitectureModel);
- topic_owned_id / subscription_owned_id identity helpers (§7.1/§7.2);
- the three §8.4 DiagnosticCode members (vocabulary only);
- Topic/Subscription uniqueness constraints;
- public contract skeleton: EntityType TOPIC/SUBSCRIPTION,
  EvidenceRelationType PUBLISHES_TO/SUBSCRIPTION_OF, DeliveryRelationType
  PUBLISHES_TO, DeliveryRef.subscription with §12.2 invariants mirrored in
  the regenerated v0.5 schemas.

A fail-closed test pins that importer/registry/canonicalization-v2 still
exclude Pub/Sub until slice 2 opens that path atomically.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings September 23, 2026 18:07
@michaelegner

Copy link
Copy Markdown
Owner Author

Review of 0a18287 against I4 Draft 0.3 (Slice 1): no blocking findings. The GO evidence and ADR cover the required semantic distinctions; the canonical/identity and public-contract changes match the slice boundary, with Pub/Sub persistence still closed. Local focused tests: 338 passed; PR CI is green. Approved from this review.

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 review overview

🟡 Changes recommended

A new unit test pins the parameter list for subscription_owned_id but does not actually enforce the keyword-only requirement, leaving an important contract invariant untested.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 1 Medium severity

Open (1)
What changed in this PR

Implements v0.5.0 I4 (Draft 0.3) Slice 1 by recording the GO decision and adding the in-memory canonical Pub/Sub foundation plus the contract/schema skeleton, while explicitly keeping Pub/Sub persistence closed until slice 2.

Changes:

  • Added Topic/Subscription canonical models, identity helpers, diagnostic vocabulary, and Neo4j uniqueness constraints.
  • Extended the public contract and regenerated v0.5 JSON schemas to include Topic/Subscription + PUBLISHES_TO/SUBSCRIPTION_OF, including DeliveryRef.subscription invariants and parity tests.
  • Added Slice 1 governance docs: decision evidence record + ADR 0017, and updated ADR index/ADR 0013 status note.
File Description
tests/​unit/​test_sources_owner_ids.py Adds golden-vector tests for new Topic/Subscription identity helpers.
tests/​unit/​test_sources_model.py Pins the exact three I4 DiagnosticCode additions.
tests/​unit/​test_canonical_pubsub_foundation.py Adds fail-closed test ensuring persistence path remains closed until slice 2.
tests/​unit/​test_architecture_intelligence_contracts.py Adds exhaustive Pydantic⇔schema parity tests for new contract rules.
tests/​integration/​test_importer.py Extends constraint-name integration assertion for Topic/Subscription.
schemas/​architecture_intelligence/​v0.5/​evidence-answer.schema.json Regenerated schema reflecting Pub/Sub vocabulary + DeliveryRef.subscription.
schemas/​architecture_intelligence/​v0.5/​drift-answer.schema.json Regenerated schema reflecting Pub/Sub vocabulary + DeliveryRef.subscription.
schemas/​architecture_intelligence/​v0.5/​architecture-answer.schema.json Regenerated schema reflecting Pub/Sub vocabulary + DeliveryRef.subscription.
docs/​specifications/​0.5.0/​i4-decision-evidence.md New independent evidence record supporting the I4 GO decision.
docs/​adr/​README.md Adds ADR 0017 entry and provenance note.
docs/​adr/​0017-source-independent-pubsub-semantics.md New ADR recording GO and retaining ADR 0013 guards.
docs/​adr/​0013-no-topic-family-without-guards.md Marks ADR 0013 as superseded in part (Topic/Subscription prohibition only).
app/​sources/​owner_ids.py Adds topic_owned_id / subscription_owned_id helpers per I4 §7.
app/​sources/​model.py Adds three I4 diagnostic codes as vocabulary.
app/​graph/​schema.py Adds Neo4j uniqueness constraints for Topic/Subscription ids.
app/​canonical/​model.py Adds Topic and Subscription canonical models (not yet on ArchitectureModel).
app/​architecture_intelligence/​contracts.py Extends contract enums and validation rules to support Topic/Subscription and subscription routing.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +261 to +266
assert list(inspect.signature(subscription_owned_id).parameters) == [
"stable_broker_id",
"normalized_namespace_or_empty",
"topic_id",
"exact_subscription_name",
]

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed in eaa2ae8: added test_pubsub_owned_id_helpers_are_keyword_only, parametrized over topic_owned_id and subscription_owned_id. It asserts every parameter is KEYWORD_ONLY and that a positional call raises TypeError. Verified by temporarily removing the * from subscription_owned_id: the new test fails. Unit suite: 1957 passed.

Addresses PR #228 review: the signature test pinned parameter names but
not the keyword-only contract shared with queue_owned_id.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@michaelegner

Copy link
Copy Markdown
Owner Author

Pushed eaa2ae8 (test-only) on top of the approved 0a18287. It resolves the one Copilot finding (keyword-only signature pin for the Pub/Sub owned-id helpers); no production code changed. Unit suite: 1957 passed; CI will re-run on the new head.

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