PLA-53: one owner for connector construction - #115
Merged
Conversation
Connector setup was written three times: a legacy per-type block, an inline
4-case switch for `connectors.instances[]` at boot, and a near-verbatim copy of
that switch in reloadConnectorInstances(). The copies had drifted apart.
Both config forms now normalize into one list — a top-level connector is just an
instance whose id defaults to its type — and a single factory constructs every
connector. One wiring function creates, routes, registers, and starts each one.
- Boot fire-and-forgets start() for every connector, matching what the comment
claimed; the instances path used to await each handshake before HTTP listen.
- Reload stops and restarts every connector, not just instance-declared ones;
instanceConnectorIds is gone and the { started, stopped, errors } shape stays.
- Session context connector names come from the live connector registry, so
instance-configured ids are listed and reloads are reflected without any
cached copy to refresh (SessionManager no longer takes connectorNames).
- template/docs/connectors.md documents instances[].
hristo2612
force-pushed
the
simplify/PLA-53-connector-single-owner
branch
from
August 3, 2026 09:01
800cdb6 to
b68ce91
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Simplify Todo PLA-53. Base
23df25ed→ head800cdb62(one commit).Selected area
Connector configuration and construction in
packages/jinn/src/gateway/server.ts— the two parallel config paths (legacy top-levelconfig.connectors.{slack,discord,telegram,whatsapp}vsconfig.connectors.instances[]) plus theconnectorNamesderivation feeding session context.Evidence of over-engineering / blended concerns
The same construct/wire/start/register block was written three times (~260 of ~357 lines, L641-997):
initConnector()helper at L665-703, used by the four top-level branches at L704-767.instances[]loop, L772-867.reloadConnectorInstances(), L872-996.The copies had drifted apart, and the drift was load-bearing:
initConnector's comment (L695-697) saysstart()must be fire-and-forget so "a slow handshake must not delay HTTP listen" — but the instances loopawaiteddiscord.start()/slack.start()/whatsapp.start()/tg.start()during boot. An instance-configured connector with a slow handshake delayed HTTP listen; a top-level one did not.connectorNames(L641-654) was built only from the four top-level keys, passed once intoSessionManager(L658), stored atsessions/manager.ts:164, read at:434to build the "## Available connectors" block (sessions/context.ts:395-399). Soinstances[]-declared connectors never appeared. Worse,SessionManager.setConfig()(:177) refreshedthis.configbut neverthis.connectorNames, so the cached copy went stale on reload.reloadConnectorInstancesskipped non-instance connectors viainstanceConnectorIds(L888-889), soPOST /api/connectors/reload(gateway/api.ts:6054-6067) silently no-opped for top-level connectors, andapi.ts:6069/:6122carried"supports both the legacy ... and named instance ids"special-casing.template/docs/connectors.md, 72 lines, zero occurrences of "instances") and had no test anywhere inpackages/jinn/src.Fixed constraint budget
Frozen by the constrain phase before any code was written:
netLineDeltamaxFilesTouchedmaxNewFilesmaxFileLinesPlus: no new dependencies, no new config options, no new package-level public exports, no single-caller abstractions, no test deleted unless the behaviour it covered was deleted.
Measured budget (real output)
Every number is inside budget.
server.tswent 1646 → 1452 lines (−194). The only pre-existing file that grew istemplate/docs/connectors.md(+31, to 103 lines), which the budget exempted as documentation. The one new file is the test file.What was deleted or clarified
Deleted — the duplication itself:
reloadConnectorInstances). Connector construction now exists in exactly one factory:grep -c 'case "telegram"'acrossserver.tstotals 1.instanceConnectorIdsis gone entirely —grep -rn instanceConnectorIds packages/jinn/srcreturns nothing.SessionManagerno longer takes aconnectorNamesconstructor param, so there is no cached copy left to go stale.Clarified — one owner per concern:
start()for every connector, so the comment now matches behaviour on both paths and no handshake delays HTTP listen. (Reload still awaits, deliberately — callers want the result.){ started, stopped, errors }response shape is unchanged.connectorProviderregistry, so instance-configured ids finally appear in employee prompts and reloads are reflected with no cache to refresh.template/docs/connectors.mdnow documentsinstances[].No new dependencies (
package.json/lockfile untouched), no new config options (instances[]already existed atshared/types.ts:928), and both the factory and the normalizer replace ≥ 2 call sites each.Test results
All gates run from the worktree at head
800cdb62:pnpm typecheck— pass, 2/2 tasks.pnpm test— pass: 310 test files, 3837 passed, 1 skipped, 0 failed.pnpm build— pass, 2/2 tasks; web bundle emitted and synced todist/web.One new test file,
packages/jinn/src/gateway/__tests__/connectors.test.ts(127 lines, 9 tests), covers normalization (legacy keys → id-defaulted instances, guards, duplicate/missing-id skip), factory dispatch, fire-and-forget boot (both never-resolving and rejectingstart()), and connector-name derivation including a mixed legacy+instance config that reflects a reload. No existing test was deleted; the small edits to four existing test files are call-signature updates for the droppedSessionManagerparam.Independent verify
Round-1 verify (separate session, read-only) returned
ship— Blockers=0, Majors=0, Minors=3. The three non-blocking minors:server.tsrather than the real boot loop.start()rejects stays registered while its id lands only inerrors[]— consistent with the legacy boot semantics.employeerouting option is now captured at normalize time rather than message time (equivalent in practice).Not verified: live handshakes against real connector credentials, and
POST /api/connectors/reloadagainst a running daemon — both covered only at the unit/normalization layer.