Roaming M1: contracts (blob store, mirror RPCs, registry) - #2

Merged
thanostourik merged 2 commits into
feature/roamingfrom
roaming/m1-contracts
Jul 4, 2026
Merged

Roaming M1: contracts (blob store, mirror RPCs, registry)#2
thanostourik merged 2 commits into
feature/roamingfrom
roaming/m1-contracts

Conversation

@thanostourik

Copy link
Copy Markdown
Owner

First M1 seam per .plans/21-roaming-workspace.md (contracts PR first). Also records the M1 analysis-pass deviations in the plan doc.

Contracts

  • WorkspaceProjectId branded id (decision D1) in baseSchemas.ts
  • New packages/contracts/src/roaming.ts: one blob record shape for every kind (D3) + manifest/conflict schemas, registry payload, RoamingProjectShell, peer record, mirror RPC schemas (syncManifest/fetchBlobs/pushBlobs), enrollment RPC schemas (D4 handshake), HTTP path constants
  • roaming:mirror auth scope (additive to the scope union)
  • roaming boolean in ServerSettings (default false) + patch schema
  • OrchestrationShellSnapshot.roamingProjects with decode-default []; roaming-project-upserted/removed shell stream variants; optional workspaceProjectId on OrchestrationProject/OrchestrationProjectShell/ProjectMetaUpdatedPayload
  • Internal (non-client-dispatchable) command project.roaming.enroll + minimal decider/projector/engine wiring so the union change keeps the tree green — emits project.meta-updated, rejects re-enroll under a different id

Verification

  • Full monorepo typecheck: no new errors (apps/mobile's 61 pre-existing dep-resolution errors match the clean-tree baseline exactly)
  • contracts 179, client-runtime 247, server orchestration/relay/server 263 tests pass

🤖 Generated with Claude Code

thanostourikand others added 2 commits July 4, 2026 17:46
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@thanostourik
thanostourik merged commit cf5fe73 into feature/roamingJul 4, 2026
@thanostourik
thanostourik deleted the roaming/m1-contracts branch July 4, 2026 14:58
thanostourik added a commit that referenced this pull request Jul 4, 2026
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 4, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 5, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 5, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 6, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 6, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 10, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 10, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 16, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 16, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 21, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 21, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 25, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 25, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 30, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 30, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 31, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 31, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Aug 1, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Aug 1, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Aug 5, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Aug 5, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for freeto 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

@thanostourik
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Roaming M1: contracts (blob store, mirror RPCs, registry) - #2

Merged
thanostourik merged 2 commits into
feature/roamingfrom
roaming/m1-contracts
Jul 4, 2026
Merged

Roaming M1: contracts (blob store, mirror RPCs, registry)#2
thanostourik merged 2 commits into
feature/roamingfrom
roaming/m1-contracts

Conversation

@thanostourik

Copy link
Copy Markdown
Owner

First M1 seam per .plans/21-roaming-workspace.md (contracts PR first). Also records the M1 analysis-pass deviations in the plan doc.

Contracts

  • WorkspaceProjectId branded id (decision D1) in baseSchemas.ts
  • New packages/contracts/src/roaming.ts: one blob record shape for every kind (D3) + manifest/conflict schemas, registry payload, RoamingProjectShell, peer record, mirror RPC schemas (syncManifest/fetchBlobs/pushBlobs), enrollment RPC schemas (D4 handshake), HTTP path constants
  • roaming:mirror auth scope (additive to the scope union)
  • roaming boolean in ServerSettings (default false) + patch schema
  • OrchestrationShellSnapshot.roamingProjects with decode-default []; roaming-project-upserted/removed shell stream variants; optional workspaceProjectId on OrchestrationProject/OrchestrationProjectShell/ProjectMetaUpdatedPayload
  • Internal (non-client-dispatchable) command project.roaming.enroll + minimal decider/projector/engine wiring so the union change keeps the tree green — emits project.meta-updated, rejects re-enroll under a different id

Verification

  • Full monorepo typecheck: no new errors (apps/mobile's 61 pre-existing dep-resolution errors match the clean-tree baseline exactly)
  • contracts 179, client-runtime 247, server orchestration/relay/server 263 tests pass

🤖 Generated with Claude Code

thanostourikand others added 2 commits July 4, 2026 17:46
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@thanostourik
thanostourik merged commit cf5fe73 into feature/roamingJul 4, 2026
@thanostourik
thanostourik deleted the roaming/m1-contracts branch July 4, 2026 14:58
thanostourik added a commit that referenced this pull request Jul 4, 2026
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 4, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 5, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 5, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 6, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 6, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 10, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 10, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 16, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 16, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 21, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 21, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 25, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 25, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 30, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 30, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 31, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 31, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Aug 1, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Aug 1, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Aug 5, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Aug 5, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for freeto 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

@thanostourik
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Roaming M1: contracts (blob store, mirror RPCs, registry) - #2

Merged
thanostourik merged 2 commits into
feature/roamingfrom
roaming/m1-contracts
Jul 4, 2026
Merged

Roaming M1: contracts (blob store, mirror RPCs, registry)#2
thanostourik merged 2 commits into
feature/roamingfrom
roaming/m1-contracts

Conversation

@thanostourik

Copy link
Copy Markdown
Owner

First M1 seam per .plans/21-roaming-workspace.md (contracts PR first). Also records the M1 analysis-pass deviations in the plan doc.

Contracts

  • WorkspaceProjectId branded id (decision D1) in baseSchemas.ts
  • New packages/contracts/src/roaming.ts: one blob record shape for every kind (D3) + manifest/conflict schemas, registry payload, RoamingProjectShell, peer record, mirror RPC schemas (syncManifest/fetchBlobs/pushBlobs), enrollment RPC schemas (D4 handshake), HTTP path constants
  • roaming:mirror auth scope (additive to the scope union)
  • roaming boolean in ServerSettings (default false) + patch schema
  • OrchestrationShellSnapshot.roamingProjects with decode-default []; roaming-project-upserted/removed shell stream variants; optional workspaceProjectId on OrchestrationProject/OrchestrationProjectShell/ProjectMetaUpdatedPayload
  • Internal (non-client-dispatchable) command project.roaming.enroll + minimal decider/projector/engine wiring so the union change keeps the tree green — emits project.meta-updated, rejects re-enroll under a different id

Verification

  • Full monorepo typecheck: no new errors (apps/mobile's 61 pre-existing dep-resolution errors match the clean-tree baseline exactly)
  • contracts 179, client-runtime 247, server orchestration/relay/server 263 tests pass

🤖 Generated with Claude Code

thanostourikand others added 2 commits July 4, 2026 17:46
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@thanostourik
thanostourik merged commit cf5fe73 into feature/roamingJul 4, 2026
@thanostourik
thanostourik deleted the roaming/m1-contracts branch July 4, 2026 14:58
thanostourik added a commit that referenced this pull request Jul 4, 2026
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 4, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 5, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 5, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 6, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 6, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 10, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 10, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 16, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 16, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 21, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 21, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 25, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 25, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 30, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 30, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 31, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 31, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Aug 1, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Aug 1, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Aug 5, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Aug 5, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for freeto 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

@thanostourik
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Roaming M1: contracts (blob store, mirror RPCs, registry) - #2

Merged
thanostourik merged 2 commits into
feature/roamingfrom
roaming/m1-contracts
Jul 4, 2026
Merged

Roaming M1: contracts (blob store, mirror RPCs, registry)#2
thanostourik merged 2 commits into
feature/roamingfrom
roaming/m1-contracts

Conversation

@thanostourik

Copy link
Copy Markdown
Owner

First M1 seam per .plans/21-roaming-workspace.md (contracts PR first). Also records the M1 analysis-pass deviations in the plan doc.

Contracts

  • WorkspaceProjectId branded id (decision D1) in baseSchemas.ts
  • New packages/contracts/src/roaming.ts: one blob record shape for every kind (D3) + manifest/conflict schemas, registry payload, RoamingProjectShell, peer record, mirror RPC schemas (syncManifest/fetchBlobs/pushBlobs), enrollment RPC schemas (D4 handshake), HTTP path constants
  • roaming:mirror auth scope (additive to the scope union)
  • roaming boolean in ServerSettings (default false) + patch schema
  • OrchestrationShellSnapshot.roamingProjects with decode-default []; roaming-project-upserted/removed shell stream variants; optional workspaceProjectId on OrchestrationProject/OrchestrationProjectShell/ProjectMetaUpdatedPayload
  • Internal (non-client-dispatchable) command project.roaming.enroll + minimal decider/projector/engine wiring so the union change keeps the tree green — emits project.meta-updated, rejects re-enroll under a different id

Verification

  • Full monorepo typecheck: no new errors (apps/mobile's 61 pre-existing dep-resolution errors match the clean-tree baseline exactly)
  • contracts 179, client-runtime 247, server orchestration/relay/server 263 tests pass

🤖 Generated with Claude Code

thanostourikand others added 2 commits July 4, 2026 17:46
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@thanostourik
thanostourik merged commit cf5fe73 into feature/roamingJul 4, 2026
@thanostourik
thanostourik deleted the roaming/m1-contracts branch July 4, 2026 14:58
thanostourik added a commit that referenced this pull request Jul 4, 2026
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 4, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 5, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 5, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 6, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 6, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 10, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 10, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 16, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 16, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 21, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 21, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 25, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 25, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 30, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 30, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 31, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 31, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Aug 1, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Aug 1, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Aug 5, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Aug 5, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for freeto 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

@thanostourik
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Roaming M1: contracts (blob store, mirror RPCs, registry) - #2

Merged
thanostourik merged 2 commits into
feature/roamingfrom
roaming/m1-contracts
Jul 4, 2026
Merged

Roaming M1: contracts (blob store, mirror RPCs, registry)#2
thanostourik merged 2 commits into
feature/roamingfrom
roaming/m1-contracts

Conversation

@thanostourik

Copy link
Copy Markdown
Owner

First M1 seam per .plans/21-roaming-workspace.md (contracts PR first). Also records the M1 analysis-pass deviations in the plan doc.

Contracts

  • WorkspaceProjectId branded id (decision D1) in baseSchemas.ts
  • New packages/contracts/src/roaming.ts: one blob record shape for every kind (D3) + manifest/conflict schemas, registry payload, RoamingProjectShell, peer record, mirror RPC schemas (syncManifest/fetchBlobs/pushBlobs), enrollment RPC schemas (D4 handshake), HTTP path constants
  • roaming:mirror auth scope (additive to the scope union)
  • roaming boolean in ServerSettings (default false) + patch schema
  • OrchestrationShellSnapshot.roamingProjects with decode-default []; roaming-project-upserted/removed shell stream variants; optional workspaceProjectId on OrchestrationProject/OrchestrationProjectShell/ProjectMetaUpdatedPayload
  • Internal (non-client-dispatchable) command project.roaming.enroll + minimal decider/projector/engine wiring so the union change keeps the tree green — emits project.meta-updated, rejects re-enroll under a different id

Verification

  • Full monorepo typecheck: no new errors (apps/mobile's 61 pre-existing dep-resolution errors match the clean-tree baseline exactly)
  • contracts 179, client-runtime 247, server orchestration/relay/server 263 tests pass

🤖 Generated with Claude Code

thanostourikand others added 2 commits July 4, 2026 17:46
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@thanostourik
thanostourik merged commit cf5fe73 into feature/roamingJul 4, 2026
@thanostourik
thanostourik deleted the roaming/m1-contracts branch July 4, 2026 14:58
thanostourik added a commit that referenced this pull request Jul 4, 2026
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 4, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 5, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 5, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 6, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 6, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 10, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 10, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 16, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 16, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 21, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 21, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 25, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 25, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 30, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 30, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 31, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 31, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Aug 1, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Aug 1, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Aug 5, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Aug 5, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for freeto 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

@thanostourik
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Roaming M1: contracts (blob store, mirror RPCs, registry) - #2

Merged
thanostourik merged 2 commits into
feature/roamingfrom
roaming/m1-contracts
Jul 4, 2026
Merged

Roaming M1: contracts (blob store, mirror RPCs, registry)#2
thanostourik merged 2 commits into
feature/roamingfrom
roaming/m1-contracts

Conversation

@thanostourik

Copy link
Copy Markdown
Owner

First M1 seam per .plans/21-roaming-workspace.md (contracts PR first). Also records the M1 analysis-pass deviations in the plan doc.

Contracts

  • WorkspaceProjectId branded id (decision D1) in baseSchemas.ts
  • New packages/contracts/src/roaming.ts: one blob record shape for every kind (D3) + manifest/conflict schemas, registry payload, RoamingProjectShell, peer record, mirror RPC schemas (syncManifest/fetchBlobs/pushBlobs), enrollment RPC schemas (D4 handshake), HTTP path constants
  • roaming:mirror auth scope (additive to the scope union)
  • roaming boolean in ServerSettings (default false) + patch schema
  • OrchestrationShellSnapshot.roamingProjects with decode-default []; roaming-project-upserted/removed shell stream variants; optional workspaceProjectId on OrchestrationProject/OrchestrationProjectShell/ProjectMetaUpdatedPayload
  • Internal (non-client-dispatchable) command project.roaming.enroll + minimal decider/projector/engine wiring so the union change keeps the tree green — emits project.meta-updated, rejects re-enroll under a different id

Verification

  • Full monorepo typecheck: no new errors (apps/mobile's 61 pre-existing dep-resolution errors match the clean-tree baseline exactly)
  • contracts 179, client-runtime 247, server orchestration/relay/server 263 tests pass

🤖 Generated with Claude Code

thanostourikand others added 2 commits July 4, 2026 17:46
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@thanostourik
thanostourik merged commit cf5fe73 into feature/roamingJul 4, 2026
@thanostourik
thanostourik deleted the roaming/m1-contracts branch July 4, 2026 14:58
thanostourik added a commit that referenced this pull request Jul 4, 2026
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 4, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 5, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 5, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 6, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 6, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 10, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 10, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 16, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 16, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 21, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 21, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 25, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 25, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 30, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 30, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 31, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 31, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Aug 1, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Aug 1, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Aug 5, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Aug 5, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for freeto 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

@thanostourik
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Roaming M1: contracts (blob store, mirror RPCs, registry) - #2

Merged
thanostourik merged 2 commits into
feature/roamingfrom
roaming/m1-contracts
Jul 4, 2026
Merged

Roaming M1: contracts (blob store, mirror RPCs, registry)#2
thanostourik merged 2 commits into
feature/roamingfrom
roaming/m1-contracts

Conversation

@thanostourik

Copy link
Copy Markdown
Owner

First M1 seam per .plans/21-roaming-workspace.md (contracts PR first). Also records the M1 analysis-pass deviations in the plan doc.

Contracts

  • WorkspaceProjectId branded id (decision D1) in baseSchemas.ts
  • New packages/contracts/src/roaming.ts: one blob record shape for every kind (D3) + manifest/conflict schemas, registry payload, RoamingProjectShell, peer record, mirror RPC schemas (syncManifest/fetchBlobs/pushBlobs), enrollment RPC schemas (D4 handshake), HTTP path constants
  • roaming:mirror auth scope (additive to the scope union)
  • roaming boolean in ServerSettings (default false) + patch schema
  • OrchestrationShellSnapshot.roamingProjects with decode-default []; roaming-project-upserted/removed shell stream variants; optional workspaceProjectId on OrchestrationProject/OrchestrationProjectShell/ProjectMetaUpdatedPayload
  • Internal (non-client-dispatchable) command project.roaming.enroll + minimal decider/projector/engine wiring so the union change keeps the tree green — emits project.meta-updated, rejects re-enroll under a different id

Verification

  • Full monorepo typecheck: no new errors (apps/mobile's 61 pre-existing dep-resolution errors match the clean-tree baseline exactly)
  • contracts 179, client-runtime 247, server orchestration/relay/server 263 tests pass

🤖 Generated with Claude Code

thanostourikand others added 2 commits July 4, 2026 17:46
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@thanostourik
thanostourik merged commit cf5fe73 into feature/roamingJul 4, 2026
@thanostourik
thanostourik deleted the roaming/m1-contracts branch July 4, 2026 14:58
thanostourik added a commit that referenced this pull request Jul 4, 2026
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 4, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 5, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 5, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 6, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 6, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 10, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 10, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 16, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 16, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 21, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 21, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 25, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 25, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 30, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 30, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 31, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 31, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Aug 1, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Aug 1, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Aug 5, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Aug 5, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for freeto 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

@thanostourik
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Roaming M1: contracts (blob store, mirror RPCs, registry) - #2

Merged
thanostourik merged 2 commits into
feature/roamingfrom
roaming/m1-contracts
Jul 4, 2026
Merged

Roaming M1: contracts (blob store, mirror RPCs, registry)#2
thanostourik merged 2 commits into
feature/roamingfrom
roaming/m1-contracts

Conversation

@thanostourik

Copy link
Copy Markdown
Owner

First M1 seam per .plans/21-roaming-workspace.md (contracts PR first). Also records the M1 analysis-pass deviations in the plan doc.

Contracts

  • WorkspaceProjectId branded id (decision D1) in baseSchemas.ts
  • New packages/contracts/src/roaming.ts: one blob record shape for every kind (D3) + manifest/conflict schemas, registry payload, RoamingProjectShell, peer record, mirror RPC schemas (syncManifest/fetchBlobs/pushBlobs), enrollment RPC schemas (D4 handshake), HTTP path constants
  • roaming:mirror auth scope (additive to the scope union)
  • roaming boolean in ServerSettings (default false) + patch schema
  • OrchestrationShellSnapshot.roamingProjects with decode-default []; roaming-project-upserted/removed shell stream variants; optional workspaceProjectId on OrchestrationProject/OrchestrationProjectShell/ProjectMetaUpdatedPayload
  • Internal (non-client-dispatchable) command project.roaming.enroll + minimal decider/projector/engine wiring so the union change keeps the tree green — emits project.meta-updated, rejects re-enroll under a different id

Verification

  • Full monorepo typecheck: no new errors (apps/mobile's 61 pre-existing dep-resolution errors match the clean-tree baseline exactly)
  • contracts 179, client-runtime 247, server orchestration/relay/server 263 tests pass

🤖 Generated with Claude Code

thanostourikand others added 2 commits July 4, 2026 17:46
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@thanostourik
thanostourik merged commit cf5fe73 into feature/roamingJul 4, 2026
@thanostourik
thanostourik deleted the roaming/m1-contracts branch July 4, 2026 14:58
thanostourik added a commit that referenced this pull request Jul 4, 2026
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 4, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 5, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 5, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 6, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 6, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 10, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 10, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 16, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 16, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 21, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 21, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 25, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 25, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 30, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 30, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 31, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Jul 31, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Aug 1, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Aug 1, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Aug 5, 2026
* Roaming M1: contracts for blob store, mirror RPCs, and registry
M1 analysis pass recorded in the plan doc (deviations: settings-flag home,
reactor gating pattern, no server-side peer endpoint discovery, mirror RPC
transport, D4 credential handshake).
Contracts:
- WorkspaceProjectId branded id (D1)
- packages/contracts/src/roaming.ts: RoamingBlobRecord/manifest/conflict (D3),
registry payload, RoamingProjectShell, peer + mirror + enrollment RPC
schemas, HTTP path constants
- roaming:mirror auth scope; `roaming` server setting (default off)
- OrchestrationShellSnapshot.roamingProjects (decode-default []) + shell
stream variants; optional workspaceProjectId on project shapes and
project.meta-updated
- internal command project.roaming.enroll with decider/projector/engine
wiring (emits project.meta-updated; double-enroll rejected)
Test literals updated for the new snapshot field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Roaming M1 contracts: apply review findings
- Contractual per-kind key derivation for the (kind, key) blob address;
workspaceProjectId documented as denormalized (opus review #1, codex P1)
- RoamingBlobConflict retains the full remote record so M2 resolution can
show both payloads (opus review #2)
- Doc notes: payload bytes authoritative for hashing; scalar-version
divergence limitation (opus review #3, #4)
- Plan doc: record the sharpened convention + the SQL-projection
persistence gap (codex P1) slated for the server enrollment PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
thanostourik added a commit that referenced this pull request Aug 5, 2026
* Roaming M1: roaming_blobs migration + RoamingBlobStore
Migration 033 (roaming_blobs + roaming_blob_conflicts, PK (kind,key)) and a
SqlClient-backed RoamingBlobStore: writeLocal (version bump, sha256 of the
verbatim payload string, author environment id), applyRemote implementing the
D3 reconciliation rule (higher version wins; equal version + different hash
records a conflict carrying the full remote record and keeps local),
manifest/get/getMany/listConflicts, and a changes stream that emits only on
accepted writes. Reuses persistence error types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: accepted writes clear superseded conflict rows
codex review P2: a recorded equal-version conflict stayed in
roaming_blob_conflicts after a later accepted write moved the key past the
contested version, so listConflicts() kept surfacing it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* RoamingBlobStore: apply independent review findings
- Serialize read-modify-write in writeLocal/applyRemote behind a semaphore:
interleaved fibers could both read before either wrote, losing updates and
defeating equal-version conflict detection (opus review #1)
- Verify ingested contentHash against the payload before any branch — a
mismatched record poisons reconciliation against every peer (opus #2)
- Replace the changes Stream with subscribeChanges (PubSub.subscribe, same
shape as ProviderInstanceRegistry): subscription is established on return,
fixing the racy stream test (opus #3) and documenting drop semantics (#4)
- Coverage: hash-mismatch rejection, concurrent same-version race, getMany
across kinds with same key, conflict replacement, idempotent-apply silence
(opus #5); precise error labels in writeLocal/applyRemote paths (opus #6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for freeto 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

@thanostourik