Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 34 additions & 7 deletions loopx/semantics/vocabulary_v0.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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"
Expand Down
20 changes: 20 additions & 0 deletions tests/architecture/test_semantic_vocabulary_drift.py
Original file line number Diff line number Diff line change
Expand Up @@ -387,3 +387,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}'