From 0e7d064ef4d5ef6d626fc4968f782ef1b8cc7779 Mon Sep 17 00:00:00 2001 From: Enrico Piovesan Date: Mon, 10 Aug 2026 01:06:00 -0600 Subject: [PATCH] Publish core.transition-action-status 1.1.0 --- .../1.1.0/contract.json | 708 ++++++++++++++++++ 1 file changed, 708 insertions(+) create mode 100644 capabilities/core/core.transition-action-status/1.1.0/contract.json diff --git a/capabilities/core/core.transition-action-status/1.1.0/contract.json b/capabilities/core/core.transition-action-status/1.1.0/contract.json new file mode 100644 index 0000000..22b9379 --- /dev/null +++ b/capabilities/core/core.transition-action-status/1.1.0/contract.json @@ -0,0 +1,708 @@ +{ + "kind": "capability_contract", + "schema_version": "1.0.0", + "id": "core.transition-action-status", + "namespace": "core", + "name": "transition-action-status", + "version": "1.1.0", + "lifecycle": "active", + "owner": { + "team": "loop", + "contact": "founders@loop.dev" + }, + "summary": "Deterministic state machine for action item status transitions (open \u2192 in_progress \u2192 blocked \u2192 snoozed \u2192 done / cancelled).", + "description": "Pure state-machine for action-item status transitions under a caller-supplied transition_config (allowed_transitions + owner_only).\n\nImplemented and smoke-tested matrix (use_cases):\n- open \u2192 in_progress (ok)\n- done \u2192 open illegal (illegal_transition)\n- open \u2192 snoozed (ok)\n- non-owner denied (not_owner)\n- in_progress \u2192 blocked (ok)\n- in_progress \u2192 done (ok)\n- blocked \u2192 in_progress (ok)\n- snoozed \u2192 open (ok)\n- open \u2192 cancelled (ok)\n- cancelled \u2192 open illegal (covers current_status=cancelled)\n- missing current_status \u2192 invalid_status\n\nKnown limitations (intentional in 1.1.0):\n- Transition graph is entirely caller-supplied; no built-in default policy\n- Does not persist status changes", + "use_cases": [ + { + "scenario": "As an owner, I want to move an item from open to in_progress, so that active work is reflected accurately.", + "input_example": { + "current_status": "open", + "requested_status": "in_progress", + "actor_id": "user-ada", + "owner_id": "user-ada", + "transition_config": { + "version": "1.0", + "allowed_transitions": { + "open": [ + "in_progress", + "cancelled", + "snoozed" + ], + "in_progress": [ + "blocked", + "done", + "cancelled", + "snoozed" + ], + "blocked": [ + "in_progress", + "cancelled" + ], + "snoozed": [ + "open", + "in_progress", + "cancelled" + ], + "done": [], + "cancelled": [] + }, + "owner_only": true + } + }, + "output_example": { + "allowed": true, + "new_status": "in_progress", + "reason_code": "ok", + "evaluation_trace": [ + "open \u2192 in_progress is allowed", + "actor is owner" + ] + }, + "happy": true, + "persona_ref": "meeting-organizer" + }, + { + "scenario": "As a system, I want an illegal transition (done \u2192 open) rejected, so that completed work cannot silently reopen.", + "input_example": { + "current_status": "done", + "requested_status": "open", + "actor_id": "user-ada", + "owner_id": "user-ada", + "transition_config": { + "version": "1.0", + "allowed_transitions": { + "open": [ + "in_progress", + "cancelled", + "snoozed" + ], + "in_progress": [ + "blocked", + "done", + "cancelled", + "snoozed" + ], + "blocked": [ + "in_progress", + "cancelled" + ], + "snoozed": [ + "open", + "in_progress", + "cancelled" + ], + "done": [], + "cancelled": [] + }, + "owner_only": true + } + }, + "output_example": { + "allowed": false, + "new_status": "done", + "reason_code": "illegal_transition", + "evaluation_trace": [ + "done has no allowed transition to open" + ] + }, + "happy": false, + "persona_ref": "runtime-engineer" + }, + { + "scenario": "As an owner, I want to snooze an open item, so that I can pause follow-up without losing the item.", + "input_example": { + "current_status": "open", + "requested_status": "snoozed", + "actor_id": "user-ada", + "owner_id": "user-ada", + "transition_config": { + "version": "1.0", + "allowed_transitions": { + "open": [ + "in_progress", + "cancelled", + "snoozed" + ], + "in_progress": [ + "blocked", + "done", + "cancelled", + "snoozed" + ], + "blocked": [ + "in_progress", + "cancelled" + ], + "snoozed": [ + "open", + "in_progress", + "cancelled" + ], + "done": [], + "cancelled": [] + }, + "owner_only": true + } + }, + "output_example": { + "allowed": true, + "new_status": "snoozed", + "reason_code": "ok", + "evaluation_trace": [ + "open \u2192 snoozed is allowed", + "actor is owner" + ] + }, + "happy": true, + "persona_ref": "meeting-organizer" + }, + { + "scenario": "As a system, I want a non-owner blocked when owner_only is true, so that only the owner can change status.", + "input_example": { + "current_status": "open", + "requested_status": "in_progress", + "actor_id": "user-bob", + "owner_id": "user-ada", + "transition_config": { + "version": "1.0", + "allowed_transitions": { + "open": [ + "in_progress", + "cancelled", + "snoozed" + ], + "in_progress": [ + "blocked", + "done", + "cancelled", + "snoozed" + ], + "blocked": [ + "in_progress", + "cancelled" + ], + "snoozed": [ + "open", + "in_progress", + "cancelled" + ], + "done": [], + "cancelled": [] + }, + "owner_only": true + } + }, + "output_example": { + "allowed": false, + "new_status": "open", + "reason_code": "not_owner", + "evaluation_trace": [ + "owner_only=true and actor is not owner" + ] + }, + "happy": false, + "persona_ref": "runtime-engineer" + }, + { + "scenario": "As an owner, I want in_progress \u2192 blocked, so that blockers are an explicit status, not tribal knowledge.", + "input_example": { + "current_status": "in_progress", + "requested_status": "blocked", + "actor_id": "user-ada", + "owner_id": "user-ada", + "transition_config": { + "version": "1.0", + "allowed_transitions": { + "open": [ + "in_progress", + "cancelled", + "snoozed" + ], + "in_progress": [ + "blocked", + "done", + "cancelled", + "snoozed" + ], + "blocked": [ + "in_progress", + "cancelled" + ], + "snoozed": [ + "open", + "in_progress", + "cancelled" + ], + "done": [], + "cancelled": [] + }, + "owner_only": true + } + }, + "output_example": { + "allowed": true, + "new_status": "blocked", + "reason_code": "ok", + "evaluation_trace": [ + "in_progress \u2192 blocked is allowed" + ] + }, + "happy": true, + "persona_ref": "meeting-organizer" + }, + { + "scenario": "As an owner, I want in_progress \u2192 done, so that finished work can leave the active queue.", + "input_example": { + "current_status": "in_progress", + "requested_status": "done", + "actor_id": "user-ada", + "owner_id": "user-ada", + "transition_config": { + "version": "1.0", + "allowed_transitions": { + "open": [ + "in_progress", + "cancelled", + "snoozed" + ], + "in_progress": [ + "blocked", + "done", + "cancelled", + "snoozed" + ], + "blocked": [ + "in_progress", + "cancelled" + ], + "snoozed": [ + "open", + "in_progress", + "cancelled" + ], + "done": [], + "cancelled": [] + }, + "owner_only": true + } + }, + "output_example": { + "allowed": true, + "new_status": "done", + "reason_code": "ok", + "evaluation_trace": [ + "in_progress \u2192 done is allowed" + ] + }, + "happy": true, + "persona_ref": "meeting-organizer" + }, + { + "scenario": "As an owner, I want blocked \u2192 in_progress, so that cleared blockers resume cleanly.", + "input_example": { + "current_status": "blocked", + "requested_status": "in_progress", + "actor_id": "user-ada", + "owner_id": "user-ada", + "transition_config": { + "version": "1.0", + "allowed_transitions": { + "open": [ + "in_progress", + "cancelled", + "snoozed" + ], + "in_progress": [ + "blocked", + "done", + "cancelled", + "snoozed" + ], + "blocked": [ + "in_progress", + "cancelled" + ], + "snoozed": [ + "open", + "in_progress", + "cancelled" + ], + "done": [], + "cancelled": [] + }, + "owner_only": true + } + }, + "output_example": { + "allowed": true, + "new_status": "in_progress", + "reason_code": "ok", + "evaluation_trace": [ + "blocked \u2192 in_progress is allowed" + ] + }, + "happy": true, + "persona_ref": "meeting-organizer" + }, + { + "scenario": "As an owner, I want snoozed \u2192 open, so that snoozed items re-enter the follow-up pool.", + "input_example": { + "current_status": "snoozed", + "requested_status": "open", + "actor_id": "user-ada", + "owner_id": "user-ada", + "transition_config": { + "version": "1.0", + "allowed_transitions": { + "open": [ + "in_progress", + "cancelled", + "snoozed" + ], + "in_progress": [ + "blocked", + "done", + "cancelled", + "snoozed" + ], + "blocked": [ + "in_progress", + "cancelled" + ], + "snoozed": [ + "open", + "in_progress", + "cancelled" + ], + "done": [], + "cancelled": [] + }, + "owner_only": true + } + }, + "output_example": { + "allowed": true, + "new_status": "open", + "reason_code": "ok", + "evaluation_trace": [ + "snoozed \u2192 open is allowed" + ] + }, + "happy": true, + "persona_ref": "meeting-organizer" + }, + { + "scenario": "As an owner, I want open \u2192 cancelled, so that abandoned work can exit without fake completion.", + "input_example": { + "current_status": "open", + "requested_status": "cancelled", + "actor_id": "user-ada", + "owner_id": "user-ada", + "transition_config": { + "version": "1.0", + "allowed_transitions": { + "open": [ + "in_progress", + "cancelled", + "snoozed" + ], + "in_progress": [ + "blocked", + "done", + "cancelled", + "snoozed" + ], + "blocked": [ + "in_progress", + "cancelled" + ], + "snoozed": [ + "open", + "in_progress", + "cancelled" + ], + "done": [], + "cancelled": [] + }, + "owner_only": true + } + }, + "output_example": { + "allowed": true, + "new_status": "cancelled", + "reason_code": "ok", + "evaluation_trace": [ + "open \u2192 cancelled is allowed" + ] + }, + "happy": true, + "persona_ref": "meeting-organizer" + }, + { + "scenario": "As a system, I want cancelled items to reject further transitions, so that cancelled work stays terminal.", + "input_example": { + "current_status": "cancelled", + "requested_status": "open", + "actor_id": "user-ada", + "owner_id": "user-ada", + "transition_config": { + "version": "1.0", + "allowed_transitions": { + "open": [ + "in_progress", + "cancelled", + "snoozed" + ], + "in_progress": [ + "blocked", + "done", + "cancelled", + "snoozed" + ], + "blocked": [ + "in_progress", + "cancelled" + ], + "snoozed": [ + "open", + "in_progress", + "cancelled" + ], + "done": [], + "cancelled": [] + }, + "owner_only": true + } + }, + "output_example": { + "allowed": false, + "new_status": "cancelled", + "reason_code": "illegal_transition", + "evaluation_trace": [ + "cancelled has no allowed transition to open" + ] + }, + "happy": false, + "persona_ref": "runtime-engineer" + }, + { + "scenario": "As a system, I want missing current_status rejected with invalid_status, so that incomplete transition requests fail closed.", + "input_example": { + "current_status": "", + "requested_status": "open", + "actor_id": "user-ada", + "owner_id": "user-ada", + "transition_config": { + "version": "1.0", + "allowed_transitions": { + "open": [ + "in_progress", + "cancelled", + "snoozed" + ], + "in_progress": [ + "blocked", + "done", + "cancelled", + "snoozed" + ], + "blocked": [ + "in_progress", + "cancelled" + ], + "snoozed": [ + "open", + "in_progress", + "cancelled" + ], + "done": [], + "cancelled": [] + }, + "owner_only": true + } + }, + "output_example": { + "allowed": false, + "new_status": "", + "reason_code": "invalid_status", + "evaluation_trace": [ + "precondition failed: required fields missing" + ] + }, + "happy": false, + "persona_ref": "runtime-engineer" + } + ], + "inputs": { + "schema": { + "type": "object", + "required": [ + "current_status", + "requested_status", + "actor_id", + "transition_config" + ], + "properties": { + "current_status": { + "type": "string", + "enum": [ + "open", + "in_progress", + "blocked", + "snoozed", + "done", + "cancelled" + ] + }, + "requested_status": { + "type": "string", + "enum": [ + "open", + "in_progress", + "blocked", + "snoozed", + "done", + "cancelled" + ] + }, + "actor_id": { + "type": "string" + }, + "owner_id": { + "type": "string" + }, + "transition_config": { + "type": "object", + "required": [ + "version", + "allowed_transitions" + ], + "properties": { + "version": { + "type": "string" + }, + "allowed_transitions": { + "type": "object" + }, + "owner_only": { + "type": "boolean", + "default": true + } + } + } + }, + "additionalProperties": false + } + }, + "outputs": { + "schema": { + "type": "object", + "required": [ + "allowed", + "new_status", + "reason_code" + ], + "properties": { + "allowed": { + "type": "boolean" + }, + "new_status": { + "type": "string" + }, + "reason_code": { + "type": "string", + "enum": [ + "ok", + "illegal_transition", + "not_owner", + "invalid_status" + ] + }, + "evaluation_trace": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + } + }, + "preconditions": [ + { + "id": "statuses-valid", + "description": "current and requested status must be known values" + } + ], + "postconditions": [ + { + "id": "deterministic", + "description": "Identical inputs produce identical outputs" + } + ], + "side_effects": [ + { + "kind": "memory_only", + "description": "Pure state machine evaluation" + } + ], + "emits": [], + "consumes": [], + "permissions": [ + { + "id": "core.transition-action-status" + } + ], + "execution": { + "binary_format": "wasm", + "entrypoint": { + "kind": "wasi-command", + "command": "run" + }, + "preferred_targets": [ + "local", + "edge", + "browser" + ], + "constraints": { + "host_api_access": "none", + "network_access": "forbidden", + "filesystem_access": "none" + } + }, + "policies": [ + { + "id": "fail-closed" + } + ], + "dependencies": [], + "provenance": { + "source": "ai-assisted", + "author": "loop-founders + traverse-capability-author", + "created_at": "2026-08-08T06:00:00Z", + "spec_ref": "core.transition-action-status@1.1.0", + "adr_refs": [ + "persona-council-review-2026-08-08" + ], + "exception_refs": [] + }, + "evidence": [ + { + "evidence_id": "core-transition-action-status-1.1.0-contract-validation", + "type": "contract_validation", + "status": "passed" + } + ], + "service_type": "stateless", + "permitted_targets": [ + "local", + "edge", + "browser", + "cloud" + ], + "artifact_type": "native", + "artifact": { + "digest": "sha256:fd73e7a813cffa11a781a79804b4261c6195cebe4d6b69e9992d591a3efa12ff", + "url": "https://github.com/traverse-framework/registry/releases/download/artifacts/core.transition-action-status-1.1.0/core-transition-action-status.wasm" + } +}