diff --git a/docs/architecture/rfcs/loopx-overall-roadmap-v0.md b/docs/architecture/rfcs/loopx-overall-roadmap-v0.md index fe2c4b8550..7ce69ea9d3 100644 --- a/docs/architecture/rfcs/loopx-overall-roadmap-v0.md +++ b/docs/architecture/rfcs/loopx-overall-roadmap-v0.md @@ -237,6 +237,18 @@ expansion follows from this roadmap revision. Do not invent unmeasured performance targets. Before each experiment/pilot, its owner freezes thresholds, baseline, budget, stop conditions and evidence scope. A post-result threshold change belongs to a new experiment. G4 correctness requires no duplicate protected effects or stale/unauthorized commits; performance and cost thresholds require separate measured qualification. +Operational status used by post-writeback sinks must stay distinct from repository +publication audits. A Goal Channel gate decision still reads current Goal and +quota state, but a repository-wide public-boundary scan belongs to explicit +`loopx check`/premerge validation, not every `refresh-state` notification +attempt. The local status APIs already use this separation. For the next +long-history qualification, measure the full `refresh-state` and `quota +spend-slot` paths separately: lock wait, history/receipt readback, state +projection, optional sink work, and result delivery. Keep the required +authority and privacy checks; optimize repeated reads only with equivalent +positive, negative, retry, and stale-generation outcomes. A fast sink no-op +is not evidence that long-history status and quota admission meet G4 SLOs. + ## 4. Every RFC: Ownership and Next Step diff --git a/loopx/extensions/lark/goal_channel_lifecycle.py b/loopx/extensions/lark/goal_channel_lifecycle.py index b689036538..dc1dab2493 100644 --- a/loopx/extensions/lark/goal_channel_lifecycle.py +++ b/loopx/extensions/lark/goal_channel_lifecycle.py @@ -197,6 +197,10 @@ def sync_human_gate_after_refresh( scan_roots=[registry_project_root(source_registry_path)], limit=20, goal_id=goal_id, + # Gate delivery needs current Goal/quota state, not a repository-wide + # publication audit on every committed refresh. Keep that audit in + # explicit check/premerge flows, as the local status APIs do. + include_public_boundary_scan=False, ) quota_packet = build_quota_should_run( status, diff --git a/tests/extensions/test_lark_goal_channel_lifecycle.py b/tests/extensions/test_lark_goal_channel_lifecycle.py index 6923ee13ef..76501c301e 100644 --- a/tests/extensions/test_lark_goal_channel_lifecycle.py +++ b/tests/extensions/test_lark_goal_channel_lifecycle.py @@ -207,10 +207,16 @@ def test_refresh_lifecycle_no_gate_checks_extension_without_delivery( ) -> None: registry_path = _registry(tmp_path) _binding(registry_path, enabled=True) + status_reads: list[dict[str, Any]] = [] + + def operational_status(**kwargs: Any) -> dict[str, Any]: + status_reads.append(kwargs) + return {"status": "fixture"} + monkeypatch.setattr( goal_channel_lifecycle, "collect_status", - lambda **kwargs: {"status": "fixture"}, + operational_status, ) monkeypatch.setattr( goal_channel_lifecycle, @@ -236,6 +242,9 @@ def test_refresh_lifecycle_no_gate_checks_extension_without_delivery( assert result["enabled"] is True assert result["status"] == "not_selected" assert result["extension_activation"] == {"status": "active"} + assert len(status_reads) == 1 + assert status_reads[0]["goal_id"] == GOAL_ID + assert status_reads[0]["include_public_boundary_scan"] is False def test_refresh_lifecycle_extension_failure_prevents_private_binding_read(