docs(adr-025): D17 — the connector is an Installable, the Connectors page is its install surface (ruled) - #1512
Conversation
…page is its install surface (ruled) Sam ruled TASK-005's decision card on 2026-09-02 (pod message 62584): A — one install verb, two doors, Connectors keeps the page. D17 records the decision, the two shapes it beat and why, the four invariants the #1509 review earned (mint last; the claim is the CAS; dispatcher-scoped selection; honest D8 phasing), and what it does not decide. The status line names D17 as the one ruled decision in the document so "Draft / Proposed" cannot be read as covering it. The implementation plan it points at is docs/plans/connector-as-installable-app.md (#1509). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
lilyshen0722
left a comment
There was a problem hiding this comment.
SR-GATE: APPROVED @ 342848e — docs-only, all checks green, D1–D17 each appear exactly once so the new number is unique within the doc.
I ran the two code claims D17 rests its shape argument on. Both hold, one more strongly than written:
- "
routes/registry/install.tsreads nocomponents[]" — confirmed, zero occurrences of the string in that file. - "its
/browsequery excludessource: 'builtin'" — confirmed, and it is a whitelist rather than an exclusion:marketplace-api.ts:678filters{ source: 'marketplace', status: 'active', 'marketplace.published': true }, sobuiltin,user,templateandremoteare all invisible there. The argument against shape B is stronger than the sentence makes it.
Two things to fix before merge:
1. Merge order. The new provenance block links [docs/plans/connector-as-installable-app.md](../plans/connector-as-installable-app.md), which is not on main — it arrives with #1509. #1509 carries no reciprocal relative link, so the dependency is one-way: land #1509 first and this link resolves on arrival; land this first and main carries a dangling link until #1509 merges.
2. The ADR-022 D2 citation overreaches. D17 glosses it as "Browse sells personas; apps are the other aisle." D2 is titled "One catalog, one flow — the entitlement fork moves from route level to step level," and its content is that everyone sees the same persona catalog at /v2/agents/browse and entitlement gates only the where-step. The first half of the gloss follows from D2 (its Browse contents are 5–7 curated personas); the second half — where apps go — is not a decision D2 makes. Shape C may well still be wrong for the reason given, but it is not D2 that says so. Suggest citing D2 for what it decides and carrying "apps are the other aisle" as D17's own reasoning.
Neither blocks the record of the ruling itself.
… writes are fenced (Kai, Vera) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ector-as-installable
…ed by an activating state (Kai) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
lilyshen0722
left a comment
There was a problem hiding this comment.
SR-GATE: APPROVED @ 80aa51b — re-gate after the fencing rework. My prior gate was at 342848ef.
D17's invariant 2 tracks #1509's rework: the lock now carries a lease and a generation, every owner write is fenced on it, and the activation is described as a split commit bridged by a recoverable activating state.
I checked that last clause against the spec it points at rather than taking it, because for a while it was not true. At #1509's d54d1dc8 the word activating appeared nowhere — the parent went straight to active on the first write — so this sentence named a state the implementation spec did not define. At #1509's current head cdfed0ec it appears 14 times as a real parent status, with the reconciler sweeping installing | activating and takeover resuming at write 2. The two documents agree now. Recording the window because the ADR is the ruling record and #1509 is what gets built: if either side moves again, this is the sentence that has to be re-checked.
The ADR-026 D6 citation holds and is well chosen — D6 specifies a "delivery nonce (supervisor generation), invalidated on requeue," and the race it was written for (an old child acking the new child's delivery) is the same shape as a revived stale owner minting over the winner's code.
My two notes from the previous gate:
- Merge order — still live. This PR links
../plans/connector-as-installable-app.mdrelatively and #1509 carries no reciprocal link, so landing #1509 first is the order that never leaves a dangling link on main. - The ADR-022 D2 gloss — I have not re-checked whether the "apps are the other aisle" wording changed; if it is still there, the point stands that D2 decides the persona catalog is unified, not where apps live.
Merge state is BLOCKED on being behind 120d8d646.
lilyshen0722
left a comment
There was a problem hiding this comment.
Resolving the hedge in my gate above rather than leaving it open: the ADR-022 D2 gloss is unchanged at 80aa51bd — :495 still reads "fights ADR-022 D2 (Browse sells personas; apps are the other aisle)".
So that note stands as filed. D2 is "One catalog, one flow — the entitlement fork moves from route level to step level"; it decides that everyone sees the same persona catalog at /v2/agents/browse and that entitlement gates only the where-step. "Browse sells personas" follows from its contents. Where apps live is not something D2 decides, so shape C may still be wrong for that reason — but it is D17's reasoning, not D2's ruling. Non-blocking; suggest citing D2 for what it decides and carrying the second clause as D17's own.
…ector-as-installable
lilyshen0722
left a comment
There was a problem hiding this comment.
SR-GATE: APPROVED @ b46e0387 — carry-forward. Rebase-only over 80aa51bd.
Same instrument as #1509: base-relative diff at each head, hashing only the +/- lines.
- base moved
120d8d64→e56342e3 - 1 file both sides,
+/-signature identical
My 80aa51bd gate stands, including the ADR-022 D2 gloss note (non-blocking, unchanged at :495). BLOCKED only on Service Tests (Tier 1 — real DBs) pending.
Ordering unchanged: land #1509 first.
…ector-as-installable
lilyshen0722
left a comment
There was a problem hiding this comment.
SR-GATE: APPROVED @ 744baef1 — carry-forward. Rebase-only over b46e0387.
Base moved e56342e3 → 5edce2e1; 1 file both sides, +/- signature identical. My b46e0387 gate stands, including the non-blocking ADR-022 D2 gloss note.
Land #1509 first or main carries a dangling relative link.
Why
Sam ruled TASK-005's decision card on 2026-09-02 (pod message 62584): A — one install verb, two doors; Connectors keeps the page. A ruled decision needs a decision record, and ADR-025 is the connector substrate's home. This lands after #1295 (the D8–D16 fold) so the numbering is unique by construction (D8+ rule).
What
docs/adr/ADR-025-connector-substrate.md: the Telegram connector becomes a builtin ADR-001 Installable (kind: app,source: builtin,scope: userper D8,webhook+event-handlercomponents); "Add a channel" on/v2/connectorsis the install verb; the projection is the existingIntegrationrow viainstallationId; the Browse card is a second door to the same verb, gated on the marketplace unlock.Proof
node scripts/verify-adr-numbering.jspasses on the tree (29 ADRs, no collisions). Docs only. Companion plan: #1509.🤖 Generated with Claude Code