From c98f3f9d6bf261616486c1e8036b777bc11b5e84 Mon Sep 17 00:00:00 2001 From: song <22676124+songoow@users.noreply.github.com> Date: Thu, 17 Sep 2026 01:39:53 -0400 Subject: [PATCH] docs(semantics): say which condition produces each effective_action value `effective_action` is the most overloaded registered slot: 32 values under one field name, carrying a decision verdict, a frontier verdict and a replay phase at once. It is the vocabulary M1 is due to split, and the one where a bare token tells a reader the least. Five of its 32 values carried a note, and all five recorded why the literal scan had missed them rather than what the value means. Document the remaining 27 against the code that decides them: - The `quota_effective_action` ladder is now readable in order: `normal_run`, `outcome_floor_recovery`, `agent_workspace_repair`, self-repair, `capability_bridge_repair`, then the blocked states, with `quota_skip` named as the final fallback rather than as a generic skip. - The five self-repair spend actions are separated by their trigger (`health_blocker`, `waiting_without_owner_projection`, `state_projection_gap`, `required_write_scope_missing_from_goal_boundary`, `user_gate_scope_projection_drift`) instead of by five similar names. - Routing consequences are stated where they exist: `governed_capability_intent` is the only value that reaches `capability_action_required`, and only with a matching intent projection; `autonomous_replan_required` is a REPLAN_ACTION; every `*_repair` name routes to `repair_required`; `terminal_no_followup` is what the controller reads as its `terminal_action` partition. - The four values a name alone misleads on are spelled out: `monitor_due` and `monitor_quiet_skip` are the two arms of one branch, `coordinate_task_bundle` replaces `normal_run` rather than adding to it, `scoped_user_gate_fallback` replaces `quota_skip` or `monitor_quiet_skip`, and `unsettled_host_turn_recovery` drops the selected Todo and refuses all three delivery modes. The five pre-existing notes are preserved verbatim and reordered to follow the registered value order, which is why the diff shows them moving. Extend the note-coverage ratchet to `effective_action` and `lease_action`, so a new value in either fails the PR path until the same diff says what produces it. Mutation-checked with a whitespace-only note. No behaviour, budget or inventory count changes. Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: song <22676124+songoow@users.noreply.github.com> --- loopx/semantics/vocabulary_v0.json | 41 +++++++++++++++---- .../test_semantic_vocabulary_drift.py | 20 +++++++++ 2 files changed, 54 insertions(+), 7 deletions(-) diff --git a/loopx/semantics/vocabulary_v0.json b/loopx/semantics/vocabulary_v0.json index b1fa138ffa..d9c01437c1 100644 --- a/loopx/semantics/vocabulary_v0.json +++ b/loopx/semantics/vocabulary_v0.json @@ -388,6 +388,40 @@ "todo_decision_scope_projection_repair", "unsettled_host_turn_recovery" ], + "value_notes": { + "agent_monitor_only": "The lane is monitor-only for this agent: not actionable by the agent, advancement work is the blocked scope, and the scheduler holds it in an agent-monitor wait.", + "agent_workspace_repair": "Workspace repair is allowed, and it outranks self-repair: the agent workspace is repaired before any further delivery. The name ends in _repair, so the route is repair_required.", + "automation_prompt_upgrade_required": "The installed automation prompt identity must be repaired first. It is one of the conditions that withholds autonomous_replan_decision_allowed, and the automation action is repair_automation_prompt_identity.", + "autonomous_replan_required": "An autonomous replan is required and its scope applies to this agent. It is one of REPLAN_ACTIONS, so the route is replan_required.", + "blocked_health": "Existing result of quota_effective_action; previously missed because the literal scan did not inspect declared return functions.", + "blocked_wait": "Existing result of quota_effective_action; previously missed because the literal scan did not inspect declared return functions.", + "boundary_projection_repair": "A required write scope is missing from the projected goal boundary; trigger required_write_scope_missing_from_goal_boundary.", + "capability_bridge_repair": "Capability repair is allowed once workspace repair and self-repair are not; the capability bridge is repaired before delivery.", + "control_plane_health_repair": "Stall repair raised by a health blocker; recommended_mode repair_control_plane_health. One of the five self-repair spend actions that stand in for the generic control_plane_repair.", + "control_plane_projection_repair": "Stall repair for a lane left waiting with no owner projection; trigger waiting_without_owner_projection.", + "control_plane_repair": "Existing result of quota_effective_action; previously missed because the literal scan did not inspect declared return functions.", + "coordinate_task_bundle": "Replaces normal_run when a ready task-orchestration contract makes this lane the coordinator: admitted or explicitly selected peer lanes are activated or resumed before its own worker-lane delivery.", + "external_evidence_observe": "An external-evidence monitor requires a read-only observation before any quiet no-op.", + "governed_capability_intent": "A governed capability intent is pending. It is the only action that routes to capability_action_required, and only when the intent projection matches the envelope goal and agent and names a command; a mismatch is a contract_error instead.", + "heartbeat_receipt_write_failed": "Writing the heartbeat receipt failed. The decision skips with state blocked_health and waits on the agent.", + "heartbeat_settled_skip": "The current heartbeat identity is fully settled. The automation stays active but quiet so a new turn can select the successor, with no quota spend for the settled turn.", + "lark_inbox_reply_due": "A direct Lark question, bot mention, or verified reply to the bot is pending a reply, and normal delivery is allowed for that reply.", + "monitor_due": "A monitor poll is due; should_run and normal delivery follow the same monitor_due flag. Its not-due counterpart in the same branch is monitor_quiet_skip.", + "monitor_quiet_skip": "A monitor poll that is not due. The scheduler maps it to a monitor wait, and it spends no quota.", + "normal_run": "Normal delivery is allowed; the first branch of quota_effective_action. With delivery_allowed and must_attempt set it routes to ready_for_host.", + "operator_gate_notify": "Existing result of quota_effective_action; previously missed because the literal scan did not inspect declared return functions.", + "operator_inbox_material_review_due": "Captured operator-inbox material is pending bounded review, and normal delivery is allowed for that review.", + "outcome_floor_recovery": "Normal delivery is refused but recovery delivery is allowed, through the quota safe bypass of kind outcome_floor_recovery.", + "peer_coordination_blocked": "Peer coordination blocks this lane. The scheduler stops it rather than holding it in a monitor wait.", + "quota_skip": "The final fallback of quota_effective_action: no delivery is allowed, no repair applies, and no more specific blocked state matched.", + "runtime_user_gate_projection_repair": "A runtime capability user-gate projection needs repair; recommended_mode repair_user_gate_projection, blocked scope user_gate_projection.", + "scoped_user_gate_fallback": "A scoped user-gate fallback applies while replan decisions are not allowed. It replaces quota_skip, monitor_quiet_skip or an absent action, and obliges one non-gated fallback segment after the user-gate notice.", + "state_projection_gap_repair": "A state-projection gap on a candidate that should run or must attempt; trigger state_projection_gap.", + "terminal_no_followup": "The Goal is terminal with no follow-up. The controller reads it as the terminal_action partition, so with no prior receipt the disposition is terminal, and the scheduler stops.", + "throttled_skip": "Existing result of quota_effective_action; previously missed because the literal scan did not inspect declared return functions.", + "todo_decision_scope_projection_repair": "A Todo user-gate scope is missing from the decision-scope projection; trigger user_gate_scope_projection_drift.", + "unsettled_host_turn_recovery": "A host Turn is unsettled and must be recovered before anything else: the selected Todo and action portfolio are dropped, should_run is set, and normal, recovery and self-repair delivery are all refused." + }, "producers": [ "loopx/cli_commands/quota.py::_apply_requested_quota_action_selection_preflight", "loopx/control_plane/quota/decision_summary.py::_task_orchestration_effective_action", @@ -409,13 +443,6 @@ "loopx/control_plane/todos/user_gate.py::apply_scoped_user_gate_fallback_projection" ], "compatibility_only": {}, - "value_notes": { - "blocked_health": "Existing result of quota_effective_action; previously missed because the literal scan did not inspect declared return functions.", - "blocked_wait": "Existing result of quota_effective_action; previously missed because the literal scan did not inspect declared return functions.", - "control_plane_repair": "Existing result of quota_effective_action; previously missed because the literal scan did not inspect declared return functions.", - "operator_gate_notify": "Existing result of quota_effective_action; previously missed because the literal scan did not inspect declared return functions.", - "throttled_skip": "Existing result of quota_effective_action; previously missed because the literal scan did not inspect declared return functions." - }, "return_producers": [ "loopx/control_plane/quota/decision_summary.py::quota_effective_action", "loopx/control_plane/quota/decision_summary.py::_task_orchestration_effective_action" diff --git a/tests/architecture/test_semantic_vocabulary_drift.py b/tests/architecture/test_semantic_vocabulary_drift.py index 760c38d9aa..82f5b117b9 100644 --- a/tests/architecture/test_semantic_vocabulary_drift.py +++ b/tests/architecture/test_semantic_vocabulary_drift.py @@ -268,3 +268,23 @@ def test_live_inventory_ignores_missing_or_stale_reports(tmp_path, monkeypatch, for name in ("first", "second")] with pytest.raises(smoke["Drift"], match="same_runtime_forks grew"): smoke["check_inventory"](registry, sources + duplicate) + + +@pytest.mark.parametrize('name', ['effective_action', 'lease_action']) +def test_remaining_kernel_values_each_carry_a_note(name): + """The two kernel vocabularies that are not Turn control flow still need notes. + + ``effective_action`` is the overloaded should-run slot M1 is due to split, so + a value here is only legible once the registry says which condition produces + it; ``lease_action`` is legacy and every value is compatibility-only, which + is exactly the kind of disposition a reader cannot infer from the name. The + note is required in the diff that adds a value, not afterwards. + """ + smoke = runpy.run_path(str(SMOKE)) + vocabulary = smoke['load_registry']()['vocabularies'][name] + notes = vocabulary.get('value_notes', {}) + undocumented = [ + value for value in vocabulary['values'] + if not str(notes.get(value) or '').strip() + ] + assert not undocumented, f'{name}: values with no value_notes entry: {undocumented}'