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
57 changes: 57 additions & 0 deletions .github/workflows/validate-examples.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: Validate Examples

on:
push:
paths:
- "examples/**"
- "references/**"
- "scripts/validate_specula.py"
- ".github/workflows/validate-examples.yml"
pull_request:
paths:
- "examples/**"
- "references/**"
- "scripts/validate_specula.py"
- ".github/workflows/validate-examples.yml"
workflow_dispatch:

jobs:
validate-examples:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install -r requirements.txt

- name: Validate every example (constitution + state machine + integration)
shell: bash
run: |
set -euo pipefail
status=0
for dir in examples/*/; do
const="${dir}constitution.json"
sm="${dir}state-machine.json"
if [[ -f "$const" && -f "$sm" ]]; then

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Fail when an example is missing a required artifact

When a PR deletes, renames, or forgets either constitution.json or state-machine.json, this condition skips the directory entirely and the workflow reports that all examples passed. Since examples/README.md defines both artifacts as required for every example, handle missing files as a validation failure rather than silently bypassing the example.

Useful? React with 👍 / 👎.

echo "::group::Validating ${dir}"
if ! python scripts/validate_specula.py \
--constitution "$const" \
--state-machine "$sm"; then
status=1
fi
echo "::endgroup::"
fi
done
if [[ "$status" -ne 0 ]]; then
echo "One or more examples failed schema/consistency validation."
exit 1
fi
echo "All examples passed schema and consistency validation."
100 changes: 74 additions & 26 deletions examples/community-space-brand/state-machine.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,52 +9,71 @@
"id": "receive_request",
"name": "Receive Request",
"type": "normal",
"allowed_transitions": ["classify_persona_mode"]
"allowed_transitions": [
"classify_persona_mode"
]
},
"classify_persona_mode": {
"id": "classify_persona_mode",
"name": "Classify Persona Mode",
"description": "Identify whether the interaction is from Esploratori (discovering, energy in movement), Attivatori (producing, energy structures), or Garanti (enabling, energy stabilises) mode.",
"type": "normal",
"allowed_transitions": ["non_judgment_check"]
"allowed_transitions": [
"non_judgment_check"
]
},
"non_judgment_check": {
"id": "non_judgment_check",
"name": "Non-Judgment Check",
"type": "normal",
"allowed_transitions": ["enabling_check", "block_stigmatizing_output"]
"allowed_transitions": [
"enabling_check",
"block_stigmatizing_output"
]
},
"enabling_check": {
"id": "enabling_check",
"name": "Enabling Check",
"description": "Verify response provides infrastructure (tools, access, resources), not just reassurance or assistance.",
"type": "normal",
"allowed_transitions": ["space_state_selection", "escalate_community_guardian"]
"allowed_transitions": [
"space_state_selection",
"escalate_community_guardian"
]
},
"space_state_selection": {
"id": "space_state_selection",
"name": "Space State Selection",
"description": "Select the appropriate activation state: essenziale, modulare, denso, or gestuale. Each state carries different intensity, color weight, and interaction mode.",
"type": "normal",
"allowed_transitions": ["generate_response"]
"allowed_transitions": [
"generate_response"
]
},
"generate_response": {
"id": "generate_response",
"name": "Generate Response",
"type": "normal",
"allowed_transitions": ["response_ready", "escalate_community_guardian"]
"allowed_transitions": [
"response_ready",
"escalate_community_guardian"
]
},
"block_stigmatizing_output": {
"id": "block_stigmatizing_output",
"name": "Block Stigmatizing Output",
"type": "escalation",
"allowed_transitions": ["generate_response"]
"allowed_transitions": [
"generate_response"
]
},
"escalate_community_guardian": {
"id": "escalate_community_guardian",
"name": "Escalate to Community Guardian",
"type": "escalation",
"allowed_transitions": ["response_ready"]
"allowed_transitions": [
"response_ready"
]
},
"response_ready": {
"id": "response_ready",
Expand All @@ -64,66 +83,72 @@
},
"transitions": [
{
"id": "t_receive_to_classify",
"id": "transition_receive_to_classify",
"from_state": "receive_request",
"to_state": "classify_persona_mode",
"trigger": "request_received"
},
{
"id": "t_classify_to_judgment",
"id": "transition_classify_to_judgment",
"from_state": "classify_persona_mode",
"to_state": "non_judgment_check",
"trigger": "persona_mode_identified"
},
{
"id": "t_judgment_pass",
"id": "transition_judgment_pass",
"from_state": "non_judgment_check",
"to_state": "enabling_check",
"trigger": "judgment_guard_passed",
"guard_ids": ["guard_non_judgment"]
"guard_ids": [
"guard_non_judgment"
]
},
{
"id": "t_judgment_fail",
"id": "transition_judgment_fail",
"from_state": "non_judgment_check",
"to_state": "block_stigmatizing_output",
"trigger": "judgment_guard_failed",
"is_fallback": true
},
{
"id": "t_enabling_pass",
"id": "transition_enabling_pass",
"from_state": "enabling_check",
"to_state": "space_state_selection",
"trigger": "enabling_guard_passed",
"guard_ids": ["guard_enabling"]
"guard_ids": [
"guard_enabling"
]
},
{
"id": "t_enabling_escalate",
"id": "transition_enabling_escalate",
"from_state": "enabling_check",
"to_state": "escalate_community_guardian",
"trigger": "enabling_guard_failed",
"is_fallback": true
},
{
"id": "t_state_to_generate",
"id": "transition_state_to_generate",
"from_state": "space_state_selection",
"to_state": "generate_response",
"trigger": "space_state_selected"
},
{
"id": "t_generate_to_ready",
"id": "transition_generate_to_ready",
"from_state": "generate_response",
"to_state": "response_ready",
"trigger": "response_validated",
"guard_ids": ["guard_no_performance_pressure"]
"guard_ids": [
"guard_no_performance_pressure"
]
},
{
"id": "t_block_to_retry",
"id": "transition_block_to_retry",
"from_state": "block_stigmatizing_output",
"to_state": "generate_response",
"trigger": "output_revised"
},
{
"id": "t_escalation_to_ready",
"id": "transition_escalation_to_ready",
"from_state": "escalate_community_guardian",
"to_state": "response_ready",
"trigger": "guardian_approved"
Expand Down Expand Up @@ -157,30 +182,53 @@
"applies_at_state": "generate_response",
"condition": "content_non_competitive AND no_achievement_framing AND no_ranking",
"principle": "principle_imagination_in_practice",
"action_on_violation": "revise",
"action_on_violation": "retry",
"severity": "high"
}
],
"space_states": {
"essenziale": {
"description": "When only what matters remains. Minimal activation.",
"tone": "quiet, essential, grounding",
"color_weight": {"sand": 0.75, "white": 0.2, "green": 0.05, "red": 0.0}
"color_weight": {
"sand": 0.75,
"white": 0.2,
"green": 0.05,
"red": 0.0
}
},
"modulare": {
"description": "When the community builds together. Structured activation.",
"tone": "collaborative, structured, enabling",
"color_weight": {"sand": 0.6, "white": 0.15, "green": 0.2, "black": 0.05, "red": 0.0}
"color_weight": {
"sand": 0.6,
"white": 0.15,
"green": 0.2,
"black": 0.05,
"red": 0.0
}
},
"denso": {
"description": "When the space is full of relationships. High presence.",
"tone": "warm, present, relational",
"color_weight": {"sand": 0.55, "white": 0.15, "green": 0.15, "black": 0.1, "red": 0.05}
"color_weight": {
"sand": 0.55,
"white": 0.15,
"green": 0.15,
"black": 0.1,
"red": 0.05
}
},
"gestuale": {
"description": "When something spontaneous happens. Emergent activation.",
"tone": "spontaneous, energetic, open",
"color_weight": {"sand": 0.5, "white": 0.15, "green": 0.15, "black": 0.1, "red": 0.1}
"color_weight": {
"sand": 0.5,
"white": 0.15,
"green": 0.15,
"black": 0.1,
"red": 0.1
}
}
},
"metadata": {
Expand Down
Loading