Skip to content

[Community Integration Proposal] Minimal AISOP execution graph for the OpenSpec propose workflow #1217

@optimization2026

Description

@optimization2026

openspec-aisop-community-integration-issue.md
openspec-propose-minimal.aisop.json

[Community Integration Proposal] Minimal AISOP execution graph for the OpenSpec propose workflow

Summary

We created a small proof of concept that expresses the OpenSpec propose workflow as an optional AISOP V1.0.0 execution graph.

This proposal does not ask OpenSpec to replace its schemas, CLI, Markdown artifacts, or existing skills. OpenSpec remains the source of truth for:

  • change and artifact status
  • artifact dependencies
  • templates and instructions
  • resolved output paths
  • project context and rules

AISOP is used only as an optional, machine-readable execution layer for the agent workflow.

Motivation

The current OpenSpec propose workflow already contains a real control-flow program:

  1. understand the requested change
  2. create a change scaffold
  3. read openspec status --json
  4. find the next ready artifact
  5. read openspec instructions --json
  6. read completed dependencies
  7. generate and write the artifact
  8. verify the file
  9. refresh status
  10. repeat until every applyRequires artifact is complete

Today this behavior is primarily represented as natural-language skill and command instructions.

The AISOP proof of concept makes the main branch, artifact loop, termination condition, and error path explicit while continuing to call the existing OpenSpec CLI.

Minimal flow

graph TD
    resolve_request[Resolve request and change name] --> input_clear{Input clear?}
    input_clear -->|no| ask_user[Ask user for clarification]
    ask_user --> resolve_request
    input_clear -->|yes| create_change[Create OpenSpec change]
    create_change --> load_status[Load OpenSpec status]
    load_status --> apply_ready{Apply requirements complete?}
    apply_ready -->|yes| finish[Show final status]
    apply_ready -->|no| load_artifact[Load next ready artifact]
    load_artifact --> generate_artifact[Generate and write artifact]
    generate_artifact --> verify_artifact[Verify artifact file]
    verify_artifact --> load_status
    finish --> end_node((End))
    create_change -.-> handle_error[Handle error]
    load_status -.-> handle_error
    load_artifact -.-> handle_error
    generate_artifact -.-> handle_error
    verify_artifact -.-> handle_error
    handle_error --> end_node
Loading

AISOP file

The following file follows the AISOP V1.0.0 two-message JSON structure and has been structurally validated with the AISOP Python reference implementation.

openspec-propose-minimal.aisop.json
[
  {
    "role": "system",
    "content": {
      "protocol": "AISOP V1.0.0",
      "axiom_0": "Human_Sovereignty_and_Wellbeing",
      "id": "openspec_propose_minimal",
      "name": "OpenSpec Propose Minimal",
      "version": "0.1.0",
      "summary": "Generate the OpenSpec artifacts required before implementation.",
      "description": "A minimal optional AISOP workflow for OpenSpec propose. OpenSpec remains authoritative for artifact status, instructions, dependencies, templates, and paths.",
      "flow_format": "mermaid",
      "loading_mode": "normal",
      "tools": [
        "shell",
        "filesystem",
        "user_interaction"
      ],
      "params": {
        "change_request": "string"
      },
      "system_prompt": "Follow OpenSpec CLI output exactly. Never invent artifact paths, templates, dependencies, context, or rules."
    }
  },
  {
    "role": "user",
    "content": {
      "instruction": "RUN aisop.main",
      "user_input": "{user_input}",
      "aisop": {
        "main": "graph TD\n    resolve_request[Resolve request and change name] --> input_clear{Input clear?}\n    input_clear -->|no| ask_user[Ask user for clarification]\n    ask_user --> resolve_request\n    input_clear -->|yes| create_change[Create OpenSpec change]\n    create_change --> load_status[Load OpenSpec status]\n    load_status --> apply_ready{Apply requirements complete?}\n    apply_ready -->|yes| finish[Show final status]\n    apply_ready -->|no| load_artifact[Load next ready artifact]\n    load_artifact --> generate_artifact[Generate and write artifact]\n    generate_artifact --> verify_artifact[Verify artifact file]\n    verify_artifact --> load_status\n    finish --> end_node((End))\n    create_change -.-> handle_error[Handle error]\n    load_status -.-> handle_error\n    load_artifact -.-> handle_error\n    generate_artifact -.-> handle_error\n    verify_artifact -.-> handle_error\n    handle_error --> end_node"
      },
      "functions": {
        "resolve_request": {
          "step1": "Read user_input and any clarification stored in runtime state. Return a structured result containing a concise change_description and a kebab-case change_name.",
          "output_mapping": "change_request",
          "constraints": [
            "Do not invent a change when the request is missing or critically ambiguous.",
            "change_name must use lowercase letters, digits, and hyphens only."
          ]
        },
        "input_clear": {
          "step1": "Return exactly 'yes' if change_request contains both a clear change_description and a valid change_name; otherwise return exactly 'no'."
        },
        "ask_user": {
          "step1": "sys.io.input('What change do you want to work on? Describe what you want to build or fix.') -> clarification",
          "step2": "sys.state.set('clarification', clarification)"
        },
        "create_change": {
          "step1": "Run `openspec new change <change_name>` using change_request.change_name.",
          "step2": "If the change already exists, ask the human whether to continue that change; do not overwrite it.",
          "on_error": {
            "command_error": "handle_error",
            "default": "handle_error"
          },
          "constraints": "Let OpenSpec resolve the planning location; do not assume repository-local paths."
        },
        "load_status": {
          "step1": "Run `openspec status --change <change_name> --json` using change_request.change_name.",
          "step2": "Parse and return applyRequires, artifacts, planningHome, changeRoot, artifactPaths, and actionContext when present.",
          "output_mapping": "openspec_status",
          "retry_policy": {
            "max_attempts": 2,
            "correction_prompt": "Re-check the active change name and OpenSpec project context."
          },
          "on_error": {
            "command_error": "handle_error",
            "default": "handle_error"
          }
        },
        "apply_ready": {
          "step1": "Return exactly 'yes' if every artifact listed in openspec_status.applyRequires has status 'done'; otherwise return exactly 'no'."
        },
        "load_artifact": {
          "step1": "Select the first artifact with status 'ready' in openspec_status.artifacts.",
          "step2": "Run `openspec instructions <artifact-id> --change <change-name> --json`.",
          "step3": "Read every completed dependency file returned by the instructions.",
          "step4": "Return artifact ID, resolvedOutputPath, template, instruction, context, rules, and dependency contents.",
          "output_mapping": "artifact_job",
          "retry_policy": {
            "max_attempts": 2,
            "correction_prompt": "Reload status and use only OpenSpec-resolved artifact data."
          },
          "on_error": {
            "command_error": "handle_error",
            "io_error": "handle_error",
            "default": "handle_error"
          },
          "constraints": [
            "Use resolvedOutputPath instead of assuming a path.",
            "Treat context and rules as constraints, not output content."
          ]
        },
        "generate_artifact": {
          "step1": "Generate the artifact using artifact_job.template and artifact_job.instruction.",
          "step2": "Apply artifact_job.context and artifact_job.rules as mandatory constraints.",
          "step3": "Use artifact_job dependency contents as source context.",
          "step4": "Write only the artifact content to artifact_job.resolvedOutputPath.",
          "on_error": {
            "io_error": "handle_error",
            "default": "handle_error"
          },
          "constraints": [
            "Do not copy OpenSpec context or rules blocks into the artifact.",
            "Do not skip required template sections.",
            "Do not write outside resolvedOutputPath."
          ],
          "execute_mode": "agent"
        },
        "verify_artifact": {
          "step1": "Verify that artifact_job.resolvedOutputPath exists and is non-empty.",
          "step2": "Confirm that the generated file follows the returned template structure.",
          "retry_policy": {
            "max_attempts": 2,
            "correction_prompt": "Recreate the artifact at the exact resolved output path."
          },
          "on_error": {
            "io_error": "handle_error",
            "assertion_error": "handle_error",
            "default": "handle_error"
          }
        },
        "finish": {
          "step1": "Run `openspec status --change <change-name>` and summarize the created artifacts.",
          "step2": "Tell the user the change is ready for `/opsx:apply` or the `openspec-apply-change` skill.",
          "constraints": "Do not claim readiness unless all applyRequires artifacts are complete."
        },
        "handle_error": {
          "step1": "Report the failed node, available error details, and the last confirmed OpenSpec state.",
          "step2": "Stop the workflow without claiming completion."
        },
        "end_node": {
          "step1": "Return the final workflow result."
        }
      }
    }
  }
]

Proposed integration boundary

AI coding assistant
        |
        v
OpenSpec-AISOP entry skill
        |
        v
AISOP execution graph
        |
        v
OpenSpec CLI JSON interfaces
        |
        v
OpenSpec schemas and artifacts

The workflow depends on the existing OpenSpec commands:

openspec new change <name>
openspec status --change <name> --json
openspec instructions <artifact-id> --change <name> --json

Non-goals

This proof of concept does not propose:

  • adding AISOP as a required OpenSpec dependency
  • replacing OpenSpec schemas
  • replacing OpenSpec artifact templates
  • changing existing /opsx:* or skill behavior
  • moving AISOP runtime code into the OpenSpec repository
  • asking OpenSpec maintainers to maintain AISOP

AIXP-Labs can maintain the integration externally.

Potential benefits

  • explicit and inspectable workflow topology
  • a visible artifact-generation loop
  • portable branching and error-routing semantics
  • reduced dependence on tool-specific prompt wording
  • a possible single source for generating different agent delivery formats
  • a foundation for later checkpoint/resume experiments

Questions

  1. Is an externally maintained community integration the appropriate path for this experiment?
  2. Are openspec status --json and openspec instructions --json suitable integration boundaries?
  3. Would the maintainers prefer this to be published as a community schema, a community skill, or a separate bridge repository?
  4. After a runnable repository is available, would a small documentation/catalog PR be welcome?

AISOP specification:

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions