Skip to content

Commit a8d11c7

Browse files
Merge remote-tracking branch 'origin/main' into codex/hosted-team-context-20260906
2 parents d9c8c4f + e260794 commit a8d11c7

20 files changed

Lines changed: 1325 additions & 223 deletions

.claude-plugin/marketplace.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"name": "engraphis-memory",
1010
"source": "./",
1111
"description": "Discipline for giving agents durable, scoped, explainable memory across sessions and repos with the Engraphis MCP tools.",
12-
"version": "1.7.2"
12+
"version": "1.7.3"
1313
}
1414
]
1515
}

.claude-plugin/plugin.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "engraphis-memory",
3-
"version": "1.7.2",
3+
"version": "1.7.3",
44
"description": "Give agents durable, scoped, explainable memory across sessions and repos via the Engraphis MCP tools. Use when you learn something worth keeping, need prior context before acting, or ask why/how a fact changed. Covers remember/recall, why/timeline, forget/pin/correct, sessions, and code search.",
55
"author": {
66
"name": "The Engraphis Authors",

.claude-plugin/skill-assets.sha256

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
595a395f048219beb8dd741443b17d889e725effa91bf3f20578bbe497f5d55e .claude-plugin/marketplace.json
2-
8294e6c2de066bd7dee01251cea42d301904cbf94a17cf8f884b26f0a67f7dc0 .claude-plugin/plugin.json
1+
1731b35c796e5ac26d7e4c7c9b77b2640d6e7478006d2c67a155f66df70bb50a .claude-plugin/marketplace.json
2+
4b2453788ff35f0c46eb8d0cd4c2491ca9352fc4bae96ee81a4c330f2709ac77 .claude-plugin/plugin.json
33
4bc8979b9ffeb97190960e551dbf4ddc6f7aeeb7b86894fd2298a59ff0001efa skills/engraphis-memory/SKILL.md
44
055655db84af07561d002f0c69744313d8413c39f3e873f941f0fa0b1e76dc66 skills/engraphis-memory/references/CONVENTIONS.md
55
62019760766ff472a76a0f81437898f39e3c1fe2631732b7b7733e50c1ad837f skills/engraphis-memory/references/SCOPING.md

CHANGELOG.md

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
# Changelog
22

33
All notable changes to Engraphis are documented here. Format loosely follows
4-
[Keep a Changelog](https://keepachangelog.com/); versions use SemVer.
5-
6-
## [Unreleased]
7-
8-
- Added schema 18 content-free command receipts and cross-process source revalidation for
9-
corrections, approvals, promotions and merges. Combined memory revisions have expected
10-
versions, operation IDs, atomic metadata/history, and typed conflicts.
11-
- Sync publication uses current canonical state and generation-aware repair; delayed work
12-
cannot restore erased vectors. Native-index failures roll back canonical changes.
13-
- Context retains distinct scoped evidence; synthesis falls back when complete source
14-
units, titles, values or conditions are lost. Answer coverage defaults to unknown.
4+
[Keep a Changelog](https://keepachangelog.com/); versions use SemVer.
5+
6+
## [Unreleased]
7+
8+
- Added schema 18 content-free command receipts and cross-process source revalidation for
9+
corrections, approvals, promotions and merges. Combined memory revisions have expected
10+
versions, operation IDs, atomic metadata/history, and typed conflicts.
11+
- Sync publication uses current canonical state and generation-aware repair; delayed work
12+
cannot restore erased vectors. Native-index failures roll back canonical changes.
13+
- Context retains distinct scoped evidence; synthesis falls back when complete source
14+
units, titles, values or conditions are lost. Answer coverage defaults to unknown.
1515
- Added project-aware memory workflows and paginated record history.
1616
- Library cursors survive unrelated activity and work across processes. File-backed
1717
browsing uses bounded live read snapshots; completed graph migrations are not
@@ -21,8 +21,28 @@ All notable changes to Engraphis are documented here. Format loosely follows
2121
- Added content-free diagnostics and build/capability information, strict coding
2222
acceptance validation and a file-backed independent-process capacity harness.
2323
These provide measurement infrastructure, not verified 100k capacity claims.
24-
25-
## [1.7.2] - 2026-09-05
24+
25+
## [1.7.3] - 2026-09-07
26+
27+
### Fixed
28+
29+
- Preserved Galaxy carrier lane and kinematic orbit invariants through central-field slider
30+
changes, including the global and core cached radii used by the next fixed slice.
31+
- Refreshed the retained local orbital speed budget when the effective local-gravity control
32+
changes, preventing a stale phase cache from masking the slider.
33+
- Kept high-density Galaxy layouts inside the strict speed cap while maintaining authored
34+
carrier and nested local orbit phase.
35+
- Bounded the zero central-gravity radius response so finite far-field envelopes cannot leave
36+
oversized kinematic carrier caches behind, and counted fallback speed-cap activations.
37+
- Bumped the deterministic Galaxy scene algorithm identity to `galaxy-v13-responsive-compact-orbits`
38+
so cached layouts cannot be confused with the revised placement contract.
39+
40+
### Tests
41+
42+
- Added deterministic regressions for central-field cache scaling and local-gravity phase
43+
invalidation, alongside the existing 500-body and browser accessibility coverage.
44+
45+
## [1.7.2] - 2026-09-05
2646

2747
### Added
2848

engraphis/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from importlib.metadata import PackageNotFoundError, version as _dist_version
44

5-
_SOURCE_VERSION = "1.7.2"
5+
_SOURCE_VERSION = "1.7.3"
66

77
try:
88
__version__ = _dist_version("engraphis")
@@ -14,7 +14,7 @@
1414
except PackageNotFoundError: # source tree without an installed distribution
1515
# Keep in step with [project] version in pyproject.toml — tests/test_packaging.py
1616
# pins the two together so a release cannot ship them out of sync.
17-
__version__ = "1.7.2"
17+
__version__ = "1.7.3"
1818

1919

2020
def _default_memory_engine_factory(**kwargs):

engraphis/commercial_manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"schema": "engraphis-commercial/v2",
3-
"version": "1.7.2",
3+
"version": "1.7.3",
44
"control_plane": "https://api.engraphis.com",
55
"account_portal": "https://api.engraphis.com/account",
66
"billing": {

engraphis/core/graph_scene.py

Lines changed: 150 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from typing import Any, Iterable, Mapping, Optional, Sequence
1717

1818

19-
ALGORITHM_VERSION = "galaxy-v12-responsive-compact-orbits"
19+
ALGORITHM_VERSION = "galaxy-v13-responsive-compact-orbits"
2020
PUBLIC_REFERENCE_ID_LIMIT = 200
2121
PUBLIC_FACET_LIMIT = 100
2222
PUBLIC_REPO_NAME_LIMIT = 100
@@ -707,47 +707,155 @@ def _community_positions(
707707
# survive the overview cap. Rank-based assignment (rank/N) fails when only the top-K
708708
# by mass are shown — they occupy a tight arc instead of spreading evenly.
709709
GOLDEN_ANGLE_RAD = math.pi * (3.0 - math.sqrt(5.0))
710-
orbital_rank = 0
711-
for community in ordered:
712-
community_id = str(community["id"])
713-
system_radius = _clamp(
714-
_finite_float(community.get("radius"), 36.0), 36.0, 10_000.0
715-
)
716-
if community_id == global_community_id:
710+
non_global = [c for c in ordered if str(c["id"]) != global_community_id]
711+
non_global_count = len(non_global)
712+
713+
if non_global_count <= 1:
714+
orbital_rank = 0
715+
for community in ordered:
716+
community_id = str(community["id"])
717+
system_radius = _clamp(
718+
_finite_float(community.get("radius"), 36.0), 36.0, 10_000.0
719+
)
720+
if community_id == global_community_id:
721+
specs.append({
722+
"id": community_id, "system_radius": system_radius,
723+
"arm": -1, "nominal_x": 0.0, "nominal_y": 0.0,
724+
})
725+
continue
726+
arm = orbital_rank % arm_count if arm_count > 0 else 0
727+
digest = hashlib.sha256(
728+
f"{ALGORITHM_VERSION}:{layout_seed}:system:{community_id}".encode("utf-8")
729+
).digest()
730+
# Small angular jitter for visual variety; kept tight so even spacing dominates.
731+
angular_jitter = (
732+
int.from_bytes(digest[:4], "big") / float(1 << 32) - 0.5
733+
) * 0.06
734+
radial_jitter = 0.95 + (
735+
int.from_bytes(digest[4:8], "big") / float(1 << 32)
736+
) * 0.10
737+
# Golden-angle based placement: each successive system advances by ≈137.5°.
738+
# This guarantees that any contiguous or sampled subset fills the circle evenly.
739+
golden_angle = base_phase + orbital_rank * GOLDEN_ANGLE_RAD
740+
angle = golden_angle + angular_jitter
741+
# Ring radius clears the core envelope. Inter-system clearance is handled
742+
# per-pair in the collision pass using actual radii, not a pessimistic global max.
743+
baseline_radius = max(
744+
core_clearance_radius,
745+
spacing * 0.90 * radial_jitter,
746+
)
717747
specs.append({
718-
"id": community_id, "system_radius": system_radius,
719-
"arm": -1, "nominal_x": 0.0, "nominal_y": 0.0,
748+
"id": community_id,
749+
"system_radius": system_radius,
750+
"arm": arm,
751+
"nominal_x": baseline_radius * math.cos(angle),
752+
"nominal_y": baseline_radius * math.sin(angle),
720753
})
721-
continue
722-
arm = orbital_rank % arm_count if arm_count > 0 else 0
723-
digest = hashlib.sha256(
724-
f"{ALGORITHM_VERSION}:{layout_seed}:system:{community_id}".encode("utf-8")
725-
).digest()
726-
# Small angular jitter for visual variety; kept tight so even spacing dominates.
727-
angular_jitter = (
728-
int.from_bytes(digest[:4], "big") / float(1 << 32) - 0.5
729-
) * 0.06
730-
radial_jitter = 0.95 + (
731-
int.from_bytes(digest[4:8], "big") / float(1 << 32)
732-
) * 0.10
733-
# Golden-angle based placement: each successive system advances by ≈137.5°.
734-
# This guarantees that any contiguous or sampled subset fills the circle evenly.
735-
golden_angle = base_phase + orbital_rank * GOLDEN_ANGLE_RAD
736-
angle = golden_angle + angular_jitter
737-
# Ring radius clears the core envelope. Inter-system clearance is handled
738-
# per-pair in the collision pass using actual radii, not a pessimistic global max.
739-
baseline_radius = max(
740-
core_clearance_radius,
741-
spacing * 1.10 * radial_jitter,
754+
orbital_rank += 1
755+
else:
756+
# Multi-tiered concentric orbital lanes: distribute communities across radial bands
757+
# (inner, mid-inner, mid-outer, outer) filling the 2D disk from the core clearance radius
758+
# outward. Each tier accommodates as many systems as geometrically fit without overlap
759+
# before placing subsequent systems on the next radial tier, interleaved with golden-angle
760+
# angular offsets. This prevents all star systems from colliding onto a single outer hoop.
761+
for community in ordered:
762+
if str(community["id"]) == global_community_id:
763+
system_radius = _clamp(
764+
_finite_float(community.get("radius"), 36.0), 36.0, 10_000.0
765+
)
766+
specs.append({
767+
"id": str(community["id"]), "system_radius": system_radius,
768+
"arm": -1, "nominal_x": 0.0, "nominal_y": 0.0,
769+
})
770+
break
771+
772+
avg_sys_radius = sum(
773+
_clamp(_finite_float(c.get("radius"), 36.0), 36.0, 10_000.0)
774+
for c in non_global
775+
) / non_global_count
776+
tier_step = max(spacing * 0.65, 2.0 * avg_sys_radius + GALAXY_SYSTEM_MIN_GAP * 0.35)
777+
778+
tiers: list[dict[str, float | int]] = []
779+
curr_radius = core_clearance_radius + avg_sys_radius
780+
remaining = non_global_count
781+
while remaining > 0:
782+
circ = 2.0 * math.pi * curr_radius
783+
envelope_size = 2.0 * avg_sys_radius + GALAXY_SYSTEM_MIN_GAP * 0.35
784+
capacity = max(2, int(circ / envelope_size))
785+
take = min(capacity, remaining)
786+
tiers.append({
787+
"radius": curr_radius,
788+
"count": take,
789+
})
790+
remaining -= take
791+
curr_radius += tier_step
792+
793+
# Homogeneous systems can share a true tier-local lattice: using the actual slot
794+
# count keeps every lane's angular gaps consistent and avoids radial fallback when
795+
# several similarly sized systems sit close to the core. Heterogeneous envelopes
796+
# retain the scene-wide low-discrepancy carrier so a large system does not create a
797+
# regular angular wall for the smaller systems. A three-or-more-tier scene is also
798+
# compact enough that local lane spacing is the safer choice even with modest size
799+
# variation.
800+
non_global_radii = [
801+
_clamp(_finite_float(c.get("radius"), 36.0), 36.0, 10_000.0)
802+
for c in non_global
803+
]
804+
homogeneous_envelopes = (
805+
max(non_global_radii, default=0.0) - min(non_global_radii, default=0.0)
806+
<= max(2.0, avg_sys_radius * 0.08)
742807
)
743-
specs.append({
744-
"id": community_id,
745-
"system_radius": system_radius,
746-
"arm": arm,
747-
"nominal_x": baseline_radius * math.cos(angle),
748-
"nominal_y": baseline_radius * math.sin(angle),
749-
})
750-
orbital_rank += 1
808+
use_tier_local_slots = len(tiers) >= 3 or homogeneous_envelopes
809+
810+
sys_idx = 0
811+
for tier_index, tier_info in enumerate(tiers):
812+
t_rad = float(tier_info["radius"])
813+
t_count = int(tier_info["count"])
814+
for tier_slot in range(t_count):
815+
community = non_global[sys_idx]
816+
community_id = str(community["id"])
817+
system_radius = _clamp(
818+
_finite_float(community.get("radius"), 36.0), 36.0, 10_000.0
819+
)
820+
arm = sys_idx % arm_count if arm_count > 0 else 0
821+
digest = hashlib.sha256(
822+
f"{ALGORITHM_VERSION}:{layout_seed}:system:{community_id}".encode("utf-8")
823+
).digest()
824+
angular_jitter = (
825+
int.from_bytes(digest[:4], "big") / float(1 << 32) - 0.5
826+
) * 0.06
827+
radial_jitter = 0.96 + (
828+
int.from_bytes(digest[4:8], "big") / float(1 << 32)
829+
) * 0.08
830+
if use_tier_local_slots:
831+
tier_phase = base_phase + tier_index * math.tau / 12.0
832+
# Use the tier's actual slot count rather than continuing the previous
833+
# tier's golden-angle rank; the deterministic phase keeps the lanes
834+
# visually distinct while the exact local lattice prevents radial
835+
# fallback from an ID-dependent jitter collapse.
836+
angle = (
837+
tier_phase
838+
+ tier_slot * math.tau / max(1, t_count)
839+
)
840+
else:
841+
# Mixed-size two-tier scenes keep a scene-wide low-discrepancy carrier so
842+
# the angular distribution remains stable across unequal envelopes.
843+
angle = base_phase + sys_idx * GOLDEN_ANGLE_RAD + angular_jitter
844+
845+
# ``preferred_targets`` applies the user-facing compactness scale below.
846+
# Tier radii are already physical lane coordinates, so compensate here or a
847+
# compactness of 0.192 would shrink every tier back through the core floor and
848+
# make the collision walk, rather than the tier plan, choose the lanes.
849+
physical_tier_radius = max(core_clearance_radius, t_rad * radial_jitter)
850+
nominal_r = physical_tier_radius / max(clean_radius_scale, 1e-9)
851+
specs.append({
852+
"id": community_id,
853+
"system_radius": system_radius,
854+
"arm": arm,
855+
"nominal_x": nominal_r * math.cos(angle),
856+
"nominal_y": nominal_r * math.sin(angle),
857+
})
858+
sys_idx += 1
751859

752860
def pack_with_radial_clearance(
753861
targets: Mapping[str, tuple[float, float]],
@@ -803,7 +911,7 @@ def collides(x: float, y: float, system_radius: float) -> bool:
803911
# The radius_scale compactness pass may shrink preferred targets inside
804912
# the core; clamp the walk's starting radius to the clearance floor so
805913
# the collision search never considers orbits inside the black hole.
806-
minimum_orbital_radius = core_outer_extent + GALAXY_SYSTEM_MIN_GAP
914+
minimum_orbital_radius = core_outer_extent + system_radius + GALAXY_SYSTEM_MIN_GAP
807915
axis_radius = max(axis_radius, minimum_orbital_radius)
808916
# Radial-only walk preserves the even angular distribution. Moving only
809917
# the system centre outward (not angularly) keeps every local star/planet
@@ -2341,7 +2449,7 @@ def _build_complete_scene(
23412449
str(all_nodes[global_anchor]["community_id"]) if global_anchor else ""
23422450
)
23432451
positions, community_hints = _community_positions(
2344-
communities, global_community_id, layout_seed, spacing=92.0
2452+
communities, global_community_id, layout_seed, spacing=74.0
23452453
)
23462454
for community in communities:
23472455
community.update(community_hints[community["id"]])
@@ -2890,7 +2998,7 @@ def eligible(node_id: str) -> bool:
28902998
graph, set(graph["community_members"]), set(graph["nodes"]), _system_radii
28912999
)
28923000
layout_positions, layout_hints = _community_positions(
2893-
layout_communities, global_community_id, layout_seed, spacing=98.0
3001+
layout_communities, global_community_id, layout_seed, spacing=78.0
28943002
)
28953003
seeded_positions = _orbital_layout_positions(
28963004
graph["nodes"], graph["community_members"], graph["community_anchors"],

0 commit comments

Comments
 (0)