build: In obsidian-connor, add a deterministic per-vault default port. Implement a small pure helper (e.g.… #14

Merged
Connor merged 1 commit from build/22685588 into main 2026-09-14 12:19:26 +00:00
Owner

What changed

build/22685588 → main — 3 file(s), +27/−9.

  • src/lib/mcp.ts
  • src/main.ts
  • test/mcp.test.ts

Why

Work is in the working copy, gate green. Here's what happened.

Most of this was already built — and that's the headline

When I opened the clone, defaultMcpPort(), vaultPortHash() (FNV-1a, 32-bit via Math.imul), MCP_PORT_BASE/MCP_PORT_SPAN, the loadSettings() migration guard and the settings-tab copy were all already there in src/lib/mcp.ts and src/main.ts, with determinism and range tests passing. My own design memory said this shipped; the step-1 trace you gave me as context said it hadn't. My memory was right and that trace was wrong — it read /home/joel/Development/obsidian-connor, which is a stale clone (one src/main.ts, no src/lib/, no test/, no test script). I've saved a note so the next task doesn't re-trace against it.

So I did not rebuild what exists. I scoped down to the one thing your spec asked for that was genuinely absent.

What I changed

The migration case had no test, for a structural reason. The "a saved port wins" rule was inline in loadSettings() (src/main.ts:1555), and main.ts imports obsidian — the gate can't load it, so the single most upgrade-dangerous rule in this feature was the one rule nothing verified.

I extracted it as a pure helper next to defaultMcpPort: […]

Gate

npm run gate ran 188 tests in 2.4s and exited 0 — green.

Built by Connor's backend backburner (dispatch 22685588) in an isolated clone; shipped deterministically by ship.py. The full build notes were spoken in conversation and stored in memory (agent-dispatch:22685588). Review is the gate.


The brief this build was given

Kept for provenance. This is the task the builder was dispatched with — not a description of the diff above.

In obsidian-connor, add a deterministic per-vault default port. Implement a small pure helper (e.g. defaultMcpPort(vaultName) in a util module) returning 27125 + hash(vaultName) % 100 using a stable non-cryptographic hash (FNV-1a or djb2) so the value is identical across restarts and platforms. Use it as the settings default instead of the literal 27125, and make sure existing vaults with an explicitly saved mcpPort keep their stored value on upgrade — only unset/never-configured settings pick up the derived default. Add unit tests covering determinism, range containment in [27125, 27224], and the migration case where a saved port is preserved. Ship as a pull request.

This task is one step of my plan: working-list item #72: obsidian-connor: both plugin instances default to mcpPort 27125, so a second vault on the same machine collides and loses the dial-out fallback path. Default the port to 27125 + hash(vaultName) % 100 (or otherwise derive a per-vault default) so the collision cannot happen by accident, and surface th

Result of earlier step 1 (read in obsidian-connor: In the obsidian-connor repo, trace how mcpPort is used end to end: where the def):

What I read

I traced mcpPort through the checkout at /home/joel/Development/obsidian-connor (main @ 177fd83) and the consumer side in /home/joel/Development/Connor.

First, a correction to my own memory. My recalled notes say this fix already shipped as PR #10 (src/lib/mcp.ts, vaultPortHash(), test/mcp.test.ts, 146 tests). None of that is in this checkout. There is exactly one source file (src/main.ts), no src/lib/, no test/, and package.json:6-9 has only dev and build — no test script at all. .git/packed-refs holds only origin/main @ 4b127df, origin/feat/mcp-server, and two build/ refs; no pr/10, no build/b6071d07. So either that work lives only in the frontend-work copy and never landed here, or this clone is stale. I did not check the remote — I can't reach it — so I'm reporting the checkout as it is and writing the plan against it.

End-to-end trace

Default. src/main.ts:67 declares mcpPort: number on ConnorSettings; src/main.ts:71-83 is the DEFAULTS literal, with the port at :80-81 under the comment "Off the Local REST API plugin's 27123/27124 so the two coexist." That is the only definition.

Load. `

### What changed `build/22685588` → `main` — 3 file(s), +27/−9. - `src/lib/mcp.ts` - `src/main.ts` - `test/mcp.test.ts` ### Why Work is in the working copy, gate green. Here's what happened. ## Most of this was already built — and that's the headline When I opened the clone, `defaultMcpPort()`, `vaultPortHash()` (FNV-1a, 32-bit via `Math.imul`), `MCP_PORT_BASE`/`MCP_PORT_SPAN`, the `loadSettings()` migration guard and the settings-tab copy were **all already there** in `src/lib/mcp.ts` and `src/main.ts`, with determinism and range tests passing. My own design memory said this shipped; the step-1 trace you gave me as context said it hadn't. **My memory was right and that trace was wrong** — it read `/home/joel/Development/obsidian-connor`, which is a stale clone (one `src/main.ts`, no `src/lib/`, no `test/`, no test script). I've saved a note so the next task doesn't re-trace against it. So I did not rebuild what exists. I scoped down to the one thing your spec asked for that was genuinely absent. ## What I changed **The migration case had no test, for a structural reason.** The "a saved port wins" rule was inline in `loadSettings()` (`src/main.ts:1555`), and `main.ts` imports `obsidian` — the gate can't load it, so the single most upgrade-dangerous rule in this feature was the one rule nothing verified. I extracted it as a pure helper next to `defaultMcpPort`: […] ### Gate `npm run gate` ran 188 tests in 2.4s and exited 0 — green. Built by Connor's backend backburner (dispatch `22685588`) in an isolated clone; shipped deterministically by `ship.py`. The full build notes were spoken in conversation and stored in memory (`agent-dispatch:22685588`). Review is the gate. --- ### The brief this build was given _Kept for provenance. This is the task the builder was dispatched with — not a description of the diff above._ > In obsidian-connor, add a deterministic per-vault default port. Implement a small pure helper (e.g. defaultMcpPort(vaultName) in a util module) returning 27125 + hash(vaultName) % 100 using a stable non-cryptographic hash (FNV-1a or djb2) so the value is identical across restarts and platforms. Use it as the settings default instead of the literal 27125, and make sure existing vaults with an explicitly saved mcpPort keep their stored value on upgrade — only unset/never-configured settings pick up the derived default. Add unit tests covering determinism, range containment in [27125, 27224], and the migration case where a saved port is preserved. Ship as a pull request. > > This task is one step of my plan: working-list item #72: obsidian-connor: both plugin instances default to mcpPort 27125, so a second vault on the same machine collides and loses the dial-out fallback path. Default the port to 27125 + hash(vaultName) % 100 (or otherwise derive a per-vault default) so the collision cannot happen by accident, and surface th > > Result of earlier step 1 (read in obsidian-connor: In the obsidian-connor repo, trace how mcpPort is used end to end: where the def): > ## What I read > > I traced `mcpPort` through the checkout at `/home/joel/Development/obsidian-connor` (main @ `177fd83`) and the consumer side in `/home/joel/Development/Connor`. > > **First, a correction to my own memory.** My recalled notes say this fix already shipped as PR #10 (`src/lib/mcp.ts`, `vaultPortHash()`, `test/mcp.test.ts`, 146 tests). **None of that is in this checkout.** There is exactly one source file (`src/main.ts`), no `src/lib/`, no `test/`, and `package.json:6-9` has only `dev` and `build` — no test script at all. `.git/packed-refs` holds only `origin/main` @ `4b127df`, `origin/feat/mcp-server`, and two `build/` refs; no `pr/10`, no `build/b6071d07`. So either that work lives only in the frontend-work copy and never landed here, or this clone is stale. I did not check the remote — I can't reach it — so I'm reporting the checkout as it is and writing the plan against it. > > ## End-to-end trace > > **Default.** `src/main.ts:67` declares `mcpPort: number` on `ConnorSettings`; `src/main.ts:71-83` is the `DEFAULTS` literal, with the port at `:80-81` under the comment *"Off the Local REST API plugin's 27123/27124 so the two coexist."* That is the only definition. > > **Load.** `
build: In obsidian-connor, add a deterministic per-vault default port.…
All checks were successful
gate / gate (pull_request) Successful in 13s
8fe486d5ec
In obsidian-connor, add a deterministic per-vault default port. Implement a small pure helper (e.g. defaultMcpPort(vaultName) in a util module) returning 27125 + hash(vaultName) % 100 using a stable non-cryptographic hash (FNV-1a or djb2) so the value is identical across restarts and platforms. Use it as the settings default instead of the literal 27125, and make sure existing vaults with an explicitly saved mcpPort keep their stored value on upgrade — only unset/never-configured settings pick up the derived default. Add unit tests covering determinism, range containment in [27125, 27224], and the migration case where a saved port is preserved. Ship as a pull request.

This task is one step of my plan: working-list item #72: obsidian-connor: both plugin instances default to mcpPort 27125, so a second vault on the same machine collides and loses the dial-out fallback path. Default the port to 27125 + hash(vaultName) % 100 (or otherwise derive a per-vault default) so the collision cannot happen by accident, and surface th

Result of earlier step 1 (read in obsidian-connor: In the obsidian-connor repo, trace how mcpPort is used end to end: where the def):
## What I read

I traced `mcpPort` through the checkout at `/home/joel/Development/obsidian-connor` (main @ `177fd83`) and the consumer side in `/home/joel/Development/Connor`.

**First, a correction to my own memory.** My recalled notes say this fix already shipped as PR #10 (`src/lib/mcp.ts`, `vaultPortHash()`, `test/mcp.test.ts`, 146 tests). **None of that is in this checkout.** There is exactly one source file (`src/main.ts`), no `src/lib/`, no `test/`, and `package.json:6-9` has only `dev` and `build` — no test script at all. `.git/packed-refs` holds only `origin/main` @ `4b127df`, `origin/feat/mcp-server`, and two `build/` refs; no `pr/10`, no `build/b6071d07`. So either that work lives only in the frontend-work copy and never landed here, or this clone is stale. I did not check the remote — I can't reach it — so I'm reporting the checkout as it is and writing the plan against it.

## End-to-end trace

**Default.** `src/main.ts:67` declares `mcpPort: number` on `ConnorSettings`; `src/main.ts:71-83` is the `DEFAULTS` literal, with the port at `:80-81` under the comment *"Off the Local REST API plugin's 27123/27124 so the two coexist."* That is the only definition.

**Load.** `

Built by my backend backburner (dispatch 22685588), diff verified by git; shipped by ship.py. Nothing merges without review.
reviewer-bot left a comment

Independent review — reviewer-bot (local model qwen2.5-coder:14b)

The PR adds a deterministic per-vault default port and refactors the logic to use it. The changes are well-scoped, correctly implemented, and include tests.

**Independent review — reviewer-bot (local model `qwen2.5-coder:14b`)** The PR adds a deterministic per-vault default port and refactors the logic to use it. The changes are well-scoped, correctly implemented, and include tests.
Connor merged commit df66d1c697 into main 2026-09-14 12:19:26 +00:00
Connor deleted branch build/22685588 2026-09-14 12:19:26 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
ZSDev/obsidian-connor!14
No description provided.