init: OpenSpec project scaffolding with proposal, design, specs, tasks

- 7 capabilities: agent-registry, task-router, receipt-protocol,
  forgejo-integration, matrix-chatops, agent-adapter, orchestrator-core
- Tech stack: Rust + axum + zigbuild (single binary)
- Forgejo as task source of truth
- Matrix as real-time ChatOps layer
- Adapter pattern for multi-agent type support
This commit is contained in:
Zer4tul 2026-05-11 14:37:43 +08:00
commit aabd52ed52
19 changed files with 1938 additions and 0 deletions

View file

@ -0,0 +1,152 @@
---
name: "OPSX: Apply"
description: Implement tasks from an OpenSpec change (Experimental)
category: Workflow
tags: [workflow, artifacts, experimental]
---
Implement tasks from an OpenSpec change.
**Input**: Optionally specify a change name (e.g., `/opsx:apply add-auth`). If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.
**Steps**
1. **Select the change**
If a name is provided, use it. Otherwise:
- Infer from conversation context if the user mentioned a change
- Auto-select if only one active change exists
- If ambiguous, run `openspec list --json` to get available changes and use the **AskUserQuestion tool** to let the user select
Always announce: "Using change: <name>" and how to override (e.g., `/opsx:apply <other>`).
2. **Check status to understand the schema**
```bash
openspec status --change "<name>" --json
```
Parse the JSON to understand:
- `schemaName`: The workflow being used (e.g., "spec-driven")
- Which artifact contains the tasks (typically "tasks" for spec-driven, check status for others)
3. **Get apply instructions**
```bash
openspec instructions apply --change "<name>" --json
```
This returns:
- Context file paths (varies by schema)
- Progress (total, complete, remaining)
- Task list with status
- Dynamic instruction based on current state
**Handle states:**
- If `state: "blocked"` (missing artifacts): show message, suggest using `/opsx:continue`
- If `state: "all_done"`: congratulate, suggest archive
- Otherwise: proceed to implementation
4. **Read context files**
Read the files listed in `contextFiles` from the apply instructions output.
The files depend on the schema being used:
- **spec-driven**: proposal, specs, design, tasks
- Other schemas: follow the contextFiles from CLI output
5. **Show current progress**
Display:
- Schema being used
- Progress: "N/M tasks complete"
- Remaining tasks overview
- Dynamic instruction from CLI
6. **Implement tasks (loop until done or blocked)**
For each pending task:
- Show which task is being worked on
- Make the code changes required
- Keep changes minimal and focused
- Mark task complete in the tasks file: `- [ ]``- [x]`
- Continue to next task
**Pause if:**
- Task is unclear → ask for clarification
- Implementation reveals a design issue → suggest updating artifacts
- Error or blocker encountered → report and wait for guidance
- User interrupts
7. **On completion or pause, show status**
Display:
- Tasks completed this session
- Overall progress: "N/M tasks complete"
- If all done: suggest archive
- If paused: explain why and wait for guidance
**Output During Implementation**
```
## Implementing: <change-name> (schema: <schema-name>)
Working on task 3/7: <task description>
[...implementation happening...]
✓ Task complete
Working on task 4/7: <task description>
[...implementation happening...]
✓ Task complete
```
**Output On Completion**
```
## Implementation Complete
**Change:** <change-name>
**Schema:** <schema-name>
**Progress:** 7/7 tasks complete ✓
### Completed This Session
- [x] Task 1
- [x] Task 2
...
All tasks complete! You can archive this change with `/opsx:archive`.
```
**Output On Pause (Issue Encountered)**
```
## Implementation Paused
**Change:** <change-name>
**Schema:** <schema-name>
**Progress:** 4/7 tasks complete
### Issue Encountered
<description of the issue>
**Options:**
1. <option 1>
2. <option 2>
3. Other approach
What would you like to do?
```
**Guardrails**
- Keep going through tasks until done or blocked
- Always read context files before starting (from the apply instructions output)
- If task is ambiguous, pause and ask before implementing
- If implementation reveals issues, pause and suggest artifact updates
- Keep code changes minimal and scoped to each task
- Update task checkbox immediately after completing each task
- Pause on errors, blockers, or unclear requirements - don't guess
- Use contextFiles from CLI output, don't assume specific file names
**Fluid Workflow Integration**
This skill supports the "actions on a change" model:
- **Can be invoked anytime**: Before all artifacts are done (if tasks exist), after partial implementation, interleaved with other actions
- **Allows artifact updates**: If implementation reveals design issues, suggest updating artifacts - not phase-locked, work fluidly

View file

@ -0,0 +1,157 @@
---
name: "OPSX: Archive"
description: Archive a completed change in the experimental workflow
category: Workflow
tags: [workflow, archive, experimental]
---
Archive a completed change in the experimental workflow.
**Input**: Optionally specify a change name after `/opsx:archive` (e.g., `/opsx:archive add-auth`). If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.
**Steps**
1. **If no change name provided, prompt for selection**
Run `openspec list --json` to get available changes. Use the **AskUserQuestion tool** to let the user select.
Show only active changes (not already archived).
Include the schema used for each change if available.
**IMPORTANT**: Do NOT guess or auto-select a change. Always let the user choose.
2. **Check artifact completion status**
Run `openspec status --change "<name>" --json` to check artifact completion.
Parse the JSON to understand:
- `schemaName`: The workflow being used
- `artifacts`: List of artifacts with their status (`done` or other)
**If any artifacts are not `done`:**
- Display warning listing incomplete artifacts
- Prompt user for confirmation to continue
- Proceed if user confirms
3. **Check task completion status**
Read the tasks file (typically `tasks.md`) to check for incomplete tasks.
Count tasks marked with `- [ ]` (incomplete) vs `- [x]` (complete).
**If incomplete tasks found:**
- Display warning showing count of incomplete tasks
- Prompt user for confirmation to continue
- Proceed if user confirms
**If no tasks file exists:** Proceed without task-related warning.
4. **Assess delta spec sync state**
Check for delta specs at `openspec/changes/<name>/specs/`. If none exist, proceed without sync prompt.
**If delta specs exist:**
- Compare each delta spec with its corresponding main spec at `openspec/specs/<capability>/spec.md`
- Determine what changes would be applied (adds, modifications, removals, renames)
- Show a combined summary before prompting
**Prompt options:**
- If changes needed: "Sync now (recommended)", "Archive without syncing"
- If already synced: "Archive now", "Sync anyway", "Cancel"
If user chooses sync, use Task tool (subagent_type: "general-purpose", prompt: "Use Skill tool to invoke openspec-sync-specs for change '<name>'. Delta spec analysis: <include the analyzed delta spec summary>"). Proceed to archive regardless of choice.
5. **Perform the archive**
Create the archive directory if it doesn't exist:
```bash
mkdir -p openspec/changes/archive
```
Generate target name using current date: `YYYY-MM-DD-<change-name>`
**Check if target already exists:**
- If yes: Fail with error, suggest renaming existing archive or using different date
- If no: Move the change directory to archive
```bash
mv openspec/changes/<name> openspec/changes/archive/YYYY-MM-DD-<name>
```
6. **Display summary**
Show archive completion summary including:
- Change name
- Schema that was used
- Archive location
- Spec sync status (synced / sync skipped / no delta specs)
- Note about any warnings (incomplete artifacts/tasks)
**Output On Success**
```
## Archive Complete
**Change:** <change-name>
**Schema:** <schema-name>
**Archived to:** openspec/changes/archive/YYYY-MM-DD-<name>/
**Specs:** ✓ Synced to main specs
All artifacts complete. All tasks complete.
```
**Output On Success (No Delta Specs)**
```
## Archive Complete
**Change:** <change-name>
**Schema:** <schema-name>
**Archived to:** openspec/changes/archive/YYYY-MM-DD-<name>/
**Specs:** No delta specs
All artifacts complete. All tasks complete.
```
**Output On Success With Warnings**
```
## Archive Complete (with warnings)
**Change:** <change-name>
**Schema:** <schema-name>
**Archived to:** openspec/changes/archive/YYYY-MM-DD-<name>/
**Specs:** Sync skipped (user chose to skip)
**Warnings:**
- Archived with 2 incomplete artifacts
- Archived with 3 incomplete tasks
- Delta spec sync was skipped (user chose to skip)
Review the archive if this was not intentional.
```
**Output On Error (Archive Exists)**
```
## Archive Failed
**Change:** <change-name>
**Target:** openspec/changes/archive/YYYY-MM-DD-<name>/
Target archive directory already exists.
**Options:**
1. Rename the existing archive
2. Delete the existing archive if it's a duplicate
3. Wait until a different date to archive
```
**Guardrails**
- Always prompt for change selection if not provided
- Use artifact graph (openspec status --json) for completion checking
- Don't block archive on warnings - just inform and confirm
- Preserve .openspec.yaml when moving to archive (it moves with the directory)
- Show clear summary of what happened
- If sync is requested, use the Skill tool to invoke `openspec-sync-specs` (agent-driven)
- If delta specs exist, always run the sync assessment and show the combined summary before prompting

View file

@ -0,0 +1,173 @@
---
name: "OPSX: Explore"
description: "Enter explore mode - think through ideas, investigate problems, clarify requirements"
category: Workflow
tags: [workflow, explore, experimental, thinking]
---
Enter explore mode. Think deeply. Visualize freely. Follow the conversation wherever it goes.
**IMPORTANT: Explore mode is for thinking, not implementing.** You may read files, search code, and investigate the codebase, but you must NEVER write code or implement features. If the user asks you to implement something, remind them to exit explore mode first and create a change proposal. You MAY create OpenSpec artifacts (proposals, designs, specs) if the user asks—that's capturing thinking, not implementing.
**This is a stance, not a workflow.** There are no fixed steps, no required sequence, no mandatory outputs. You're a thinking partner helping the user explore.
**Input**: The argument after `/opsx:explore` is whatever the user wants to think about. Could be:
- A vague idea: "real-time collaboration"
- A specific problem: "the auth system is getting unwieldy"
- A change name: "add-dark-mode" (to explore in context of that change)
- A comparison: "postgres vs sqlite for this"
- Nothing (just enter explore mode)
---
## The Stance
- **Curious, not prescriptive** - Ask questions that emerge naturally, don't follow a script
- **Open threads, not interrogations** - Surface multiple interesting directions and let the user follow what resonates. Don't funnel them through a single path of questions.
- **Visual** - Use ASCII diagrams liberally when they'd help clarify thinking
- **Adaptive** - Follow interesting threads, pivot when new information emerges
- **Patient** - Don't rush to conclusions, let the shape of the problem emerge
- **Grounded** - Explore the actual codebase when relevant, don't just theorize
---
## What You Might Do
Depending on what the user brings, you might:
**Explore the problem space**
- Ask clarifying questions that emerge from what they said
- Challenge assumptions
- Reframe the problem
- Find analogies
**Investigate the codebase**
- Map existing architecture relevant to the discussion
- Find integration points
- Identify patterns already in use
- Surface hidden complexity
**Compare options**
- Brainstorm multiple approaches
- Build comparison tables
- Sketch tradeoffs
- Recommend a path (if asked)
**Visualize**
```
┌─────────────────────────────────────────┐
│ Use ASCII diagrams liberally │
├─────────────────────────────────────────┤
│ │
│ ┌────────┐ ┌────────┐ │
│ │ State │────────▶│ State │ │
│ │ A │ │ B │ │
│ └────────┘ └────────┘ │
│ │
│ System diagrams, state machines, │
│ data flows, architecture sketches, │
│ dependency graphs, comparison tables │
│ │
└─────────────────────────────────────────┘
```
**Surface risks and unknowns**
- Identify what could go wrong
- Find gaps in understanding
- Suggest spikes or investigations
---
## OpenSpec Awareness
You have full context of the OpenSpec system. Use it naturally, don't force it.
### Check for context
At the start, quickly check what exists:
```bash
openspec list --json
```
This tells you:
- If there are active changes
- Their names, schemas, and status
- What the user might be working on
If the user mentioned a specific change name, read its artifacts for context.
### When no change exists
Think freely. When insights crystallize, you might offer:
- "This feels solid enough to start a change. Want me to create a proposal?"
- Or keep exploring - no pressure to formalize
### When a change exists
If the user mentions a change or you detect one is relevant:
1. **Read existing artifacts for context**
- `openspec/changes/<name>/proposal.md`
- `openspec/changes/<name>/design.md`
- `openspec/changes/<name>/tasks.md`
- etc.
2. **Reference them naturally in conversation**
- "Your design mentions using Redis, but we just realized SQLite fits better..."
- "The proposal scopes this to premium users, but we're now thinking everyone..."
3. **Offer to capture when decisions are made**
| Insight Type | Where to Capture |
|--------------|------------------|
| New requirement discovered | `specs/<capability>/spec.md` |
| Requirement changed | `specs/<capability>/spec.md` |
| Design decision made | `design.md` |
| Scope changed | `proposal.md` |
| New work identified | `tasks.md` |
| Assumption invalidated | Relevant artifact |
Example offers:
- "That's a design decision. Capture it in design.md?"
- "This is a new requirement. Add it to specs?"
- "This changes scope. Update the proposal?"
4. **The user decides** - Offer and move on. Don't pressure. Don't auto-capture.
---
## What You Don't Have To Do
- Follow a script
- Ask the same questions every time
- Produce a specific artifact
- Reach a conclusion
- Stay on topic if a tangent is valuable
- Be brief (this is thinking time)
---
## Ending Discovery
There's no required ending. Discovery might:
- **Flow into a proposal**: "Ready to start? I can create a change proposal."
- **Result in artifact updates**: "Updated design.md with these decisions"
- **Just provide clarity**: User has what they need, moves on
- **Continue later**: "We can pick this up anytime"
When things crystallize, you might offer a summary - but it's optional. Sometimes the thinking IS the value.
---
## Guardrails
- **Don't implement** - Never write code or implement features. Creating OpenSpec artifacts is fine, writing application code is not.
- **Don't fake understanding** - If something is unclear, dig deeper
- **Don't rush** - Discovery is thinking time, not task time
- **Don't force structure** - Let patterns emerge naturally
- **Don't auto-capture** - Offer to save insights, don't just do it
- **Do visualize** - A good diagram is worth many paragraphs
- **Do explore the codebase** - Ground discussions in reality
- **Do question assumptions** - Including the user's and your own

View file

@ -0,0 +1,106 @@
---
name: "OPSX: Propose"
description: Propose a new change - create it and generate all artifacts in one step
category: Workflow
tags: [workflow, artifacts, experimental]
---
Propose a new change - create the change and generate all artifacts in one step.
I'll create a change with artifacts:
- proposal.md (what & why)
- design.md (how)
- tasks.md (implementation steps)
When ready to implement, run /opsx:apply
---
**Input**: The argument after `/opsx:propose` is the change name (kebab-case), OR a description of what the user wants to build.
**Steps**
1. **If no input provided, ask what they want to build**
Use the **AskUserQuestion tool** (open-ended, no preset options) to ask:
> "What change do you want to work on? Describe what you want to build or fix."
From their description, derive a kebab-case name (e.g., "add user authentication" → `add-user-auth`).
**IMPORTANT**: Do NOT proceed without understanding what the user wants to build.
2. **Create the change directory**
```bash
openspec new change "<name>"
```
This creates a scaffolded change at `openspec/changes/<name>/` with `.openspec.yaml`.
3. **Get the artifact build order**
```bash
openspec status --change "<name>" --json
```
Parse the JSON to get:
- `applyRequires`: array of artifact IDs needed before implementation (e.g., `["tasks"]`)
- `artifacts`: list of all artifacts with their status and dependencies
4. **Create artifacts in sequence until apply-ready**
Use the **TodoWrite tool** to track progress through the artifacts.
Loop through artifacts in dependency order (artifacts with no pending dependencies first):
a. **For each artifact that is `ready` (dependencies satisfied)**:
- Get instructions:
```bash
openspec instructions <artifact-id> --change "<name>" --json
```
- The instructions JSON includes:
- `context`: Project background (constraints for you - do NOT include in output)
- `rules`: Artifact-specific rules (constraints for you - do NOT include in output)
- `template`: The structure to use for your output file
- `instruction`: Schema-specific guidance for this artifact type
- `outputPath`: Where to write the artifact
- `dependencies`: Completed artifacts to read for context
- Read any completed dependency files for context
- Create the artifact file using `template` as the structure
- Apply `context` and `rules` as constraints - but do NOT copy them into the file
- Show brief progress: "Created <artifact-id>"
b. **Continue until all `applyRequires` artifacts are complete**
- After creating each artifact, re-run `openspec status --change "<name>" --json`
- Check if every artifact ID in `applyRequires` has `status: "done"` in the artifacts array
- Stop when all `applyRequires` artifacts are done
c. **If an artifact requires user input** (unclear context):
- Use **AskUserQuestion tool** to clarify
- Then continue with creation
5. **Show final status**
```bash
openspec status --change "<name>"
```
**Output**
After completing all artifacts, summarize:
- Change name and location
- List of artifacts created with brief descriptions
- What's ready: "All artifacts created! Ready for implementation."
- Prompt: "Run `/opsx:apply` to start implementing."
**Artifact Creation Guidelines**
- Follow the `instruction` field from `openspec instructions` for each artifact type
- The schema defines what each artifact should contain - follow it
- Read dependency artifacts for context before creating new ones
- Use `template` as the structure for your output file - fill in its sections
- **IMPORTANT**: `context` and `rules` are constraints for YOU, not content for the file
- Do NOT copy `<context>`, `<rules>`, `<project_context>` blocks into the artifact
- These guide what you write, but should never appear in the output
**Guardrails**
- Create ALL artifacts needed for implementation (as defined by schema's `apply.requires`)
- Always read dependency artifacts before creating a new one
- If context is critically unclear, ask the user - but prefer making reasonable decisions to keep momentum
- If a change with that name already exists, ask if user wants to continue it or create a new one
- Verify each artifact file exists after writing before proceeding to next

View file

@ -0,0 +1,156 @@
---
name: openspec-apply-change
description: Implement tasks from an OpenSpec change. Use when the user wants to start implementing, continue implementation, or work through tasks.
license: MIT
compatibility: Requires openspec CLI.
metadata:
author: openspec
version: "1.0"
generatedBy: "1.2.0"
---
Implement tasks from an OpenSpec change.
**Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.
**Steps**
1. **Select the change**
If a name is provided, use it. Otherwise:
- Infer from conversation context if the user mentioned a change
- Auto-select if only one active change exists
- If ambiguous, run `openspec list --json` to get available changes and use the **AskUserQuestion tool** to let the user select
Always announce: "Using change: <name>" and how to override (e.g., `/opsx:apply <other>`).
2. **Check status to understand the schema**
```bash
openspec status --change "<name>" --json
```
Parse the JSON to understand:
- `schemaName`: The workflow being used (e.g., "spec-driven")
- Which artifact contains the tasks (typically "tasks" for spec-driven, check status for others)
3. **Get apply instructions**
```bash
openspec instructions apply --change "<name>" --json
```
This returns:
- Context file paths (varies by schema - could be proposal/specs/design/tasks or spec/tests/implementation/docs)
- Progress (total, complete, remaining)
- Task list with status
- Dynamic instruction based on current state
**Handle states:**
- If `state: "blocked"` (missing artifacts): show message, suggest using openspec-continue-change
- If `state: "all_done"`: congratulate, suggest archive
- Otherwise: proceed to implementation
4. **Read context files**
Read the files listed in `contextFiles` from the apply instructions output.
The files depend on the schema being used:
- **spec-driven**: proposal, specs, design, tasks
- Other schemas: follow the contextFiles from CLI output
5. **Show current progress**
Display:
- Schema being used
- Progress: "N/M tasks complete"
- Remaining tasks overview
- Dynamic instruction from CLI
6. **Implement tasks (loop until done or blocked)**
For each pending task:
- Show which task is being worked on
- Make the code changes required
- Keep changes minimal and focused
- Mark task complete in the tasks file: `- [ ]``- [x]`
- Continue to next task
**Pause if:**
- Task is unclear → ask for clarification
- Implementation reveals a design issue → suggest updating artifacts
- Error or blocker encountered → report and wait for guidance
- User interrupts
7. **On completion or pause, show status**
Display:
- Tasks completed this session
- Overall progress: "N/M tasks complete"
- If all done: suggest archive
- If paused: explain why and wait for guidance
**Output During Implementation**
```
## Implementing: <change-name> (schema: <schema-name>)
Working on task 3/7: <task description>
[...implementation happening...]
✓ Task complete
Working on task 4/7: <task description>
[...implementation happening...]
✓ Task complete
```
**Output On Completion**
```
## Implementation Complete
**Change:** <change-name>
**Schema:** <schema-name>
**Progress:** 7/7 tasks complete ✓
### Completed This Session
- [x] Task 1
- [x] Task 2
...
All tasks complete! Ready to archive this change.
```
**Output On Pause (Issue Encountered)**
```
## Implementation Paused
**Change:** <change-name>
**Schema:** <schema-name>
**Progress:** 4/7 tasks complete
### Issue Encountered
<description of the issue>
**Options:**
1. <option 1>
2. <option 2>
3. Other approach
What would you like to do?
```
**Guardrails**
- Keep going through tasks until done or blocked
- Always read context files before starting (from the apply instructions output)
- If task is ambiguous, pause and ask before implementing
- If implementation reveals issues, pause and suggest artifact updates
- Keep code changes minimal and scoped to each task
- Update task checkbox immediately after completing each task
- Pause on errors, blockers, or unclear requirements - don't guess
- Use contextFiles from CLI output, don't assume specific file names
**Fluid Workflow Integration**
This skill supports the "actions on a change" model:
- **Can be invoked anytime**: Before all artifacts are done (if tasks exist), after partial implementation, interleaved with other actions
- **Allows artifact updates**: If implementation reveals design issues, suggest updating artifacts - not phase-locked, work fluidly

View file

@ -0,0 +1,114 @@
---
name: openspec-archive-change
description: Archive a completed change in the experimental workflow. Use when the user wants to finalize and archive a change after implementation is complete.
license: MIT
compatibility: Requires openspec CLI.
metadata:
author: openspec
version: "1.0"
generatedBy: "1.2.0"
---
Archive a completed change in the experimental workflow.
**Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.
**Steps**
1. **If no change name provided, prompt for selection**
Run `openspec list --json` to get available changes. Use the **AskUserQuestion tool** to let the user select.
Show only active changes (not already archived).
Include the schema used for each change if available.
**IMPORTANT**: Do NOT guess or auto-select a change. Always let the user choose.
2. **Check artifact completion status**
Run `openspec status --change "<name>" --json` to check artifact completion.
Parse the JSON to understand:
- `schemaName`: The workflow being used
- `artifacts`: List of artifacts with their status (`done` or other)
**If any artifacts are not `done`:**
- Display warning listing incomplete artifacts
- Use **AskUserQuestion tool** to confirm user wants to proceed
- Proceed if user confirms
3. **Check task completion status**
Read the tasks file (typically `tasks.md`) to check for incomplete tasks.
Count tasks marked with `- [ ]` (incomplete) vs `- [x]` (complete).
**If incomplete tasks found:**
- Display warning showing count of incomplete tasks
- Use **AskUserQuestion tool** to confirm user wants to proceed
- Proceed if user confirms
**If no tasks file exists:** Proceed without task-related warning.
4. **Assess delta spec sync state**
Check for delta specs at `openspec/changes/<name>/specs/`. If none exist, proceed without sync prompt.
**If delta specs exist:**
- Compare each delta spec with its corresponding main spec at `openspec/specs/<capability>/spec.md`
- Determine what changes would be applied (adds, modifications, removals, renames)
- Show a combined summary before prompting
**Prompt options:**
- If changes needed: "Sync now (recommended)", "Archive without syncing"
- If already synced: "Archive now", "Sync anyway", "Cancel"
If user chooses sync, use Task tool (subagent_type: "general-purpose", prompt: "Use Skill tool to invoke openspec-sync-specs for change '<name>'. Delta spec analysis: <include the analyzed delta spec summary>"). Proceed to archive regardless of choice.
5. **Perform the archive**
Create the archive directory if it doesn't exist:
```bash
mkdir -p openspec/changes/archive
```
Generate target name using current date: `YYYY-MM-DD-<change-name>`
**Check if target already exists:**
- If yes: Fail with error, suggest renaming existing archive or using different date
- If no: Move the change directory to archive
```bash
mv openspec/changes/<name> openspec/changes/archive/YYYY-MM-DD-<name>
```
6. **Display summary**
Show archive completion summary including:
- Change name
- Schema that was used
- Archive location
- Whether specs were synced (if applicable)
- Note about any warnings (incomplete artifacts/tasks)
**Output On Success**
```
## Archive Complete
**Change:** <change-name>
**Schema:** <schema-name>
**Archived to:** openspec/changes/archive/YYYY-MM-DD-<name>/
**Specs:** ✓ Synced to main specs (or "No delta specs" or "Sync skipped")
All artifacts complete. All tasks complete.
```
**Guardrails**
- Always prompt for change selection if not provided
- Use artifact graph (openspec status --json) for completion checking
- Don't block archive on warnings - just inform and confirm
- Preserve .openspec.yaml when moving to archive (it moves with the directory)
- Show clear summary of what happened
- If sync is requested, use openspec-sync-specs approach (agent-driven)
- If delta specs exist, always run the sync assessment and show the combined summary before prompting

View file

@ -0,0 +1,288 @@
---
name: openspec-explore
description: Enter explore mode - a thinking partner for exploring ideas, investigating problems, and clarifying requirements. Use when the user wants to think through something before or during a change.
license: MIT
compatibility: Requires openspec CLI.
metadata:
author: openspec
version: "1.0"
generatedBy: "1.2.0"
---
Enter explore mode. Think deeply. Visualize freely. Follow the conversation wherever it goes.
**IMPORTANT: Explore mode is for thinking, not implementing.** You may read files, search code, and investigate the codebase, but you must NEVER write code or implement features. If the user asks you to implement something, remind them to exit explore mode first and create a change proposal. You MAY create OpenSpec artifacts (proposals, designs, specs) if the user asks—that's capturing thinking, not implementing.
**This is a stance, not a workflow.** There are no fixed steps, no required sequence, no mandatory outputs. You're a thinking partner helping the user explore.
---
## The Stance
- **Curious, not prescriptive** - Ask questions that emerge naturally, don't follow a script
- **Open threads, not interrogations** - Surface multiple interesting directions and let the user follow what resonates. Don't funnel them through a single path of questions.
- **Visual** - Use ASCII diagrams liberally when they'd help clarify thinking
- **Adaptive** - Follow interesting threads, pivot when new information emerges
- **Patient** - Don't rush to conclusions, let the shape of the problem emerge
- **Grounded** - Explore the actual codebase when relevant, don't just theorize
---
## What You Might Do
Depending on what the user brings, you might:
**Explore the problem space**
- Ask clarifying questions that emerge from what they said
- Challenge assumptions
- Reframe the problem
- Find analogies
**Investigate the codebase**
- Map existing architecture relevant to the discussion
- Find integration points
- Identify patterns already in use
- Surface hidden complexity
**Compare options**
- Brainstorm multiple approaches
- Build comparison tables
- Sketch tradeoffs
- Recommend a path (if asked)
**Visualize**
```
┌─────────────────────────────────────────┐
│ Use ASCII diagrams liberally │
├─────────────────────────────────────────┤
│ │
│ ┌────────┐ ┌────────┐ │
│ │ State │────────▶│ State │ │
│ │ A │ │ B │ │
│ └────────┘ └────────┘ │
│ │
│ System diagrams, state machines, │
│ data flows, architecture sketches, │
│ dependency graphs, comparison tables │
│ │
└─────────────────────────────────────────┘
```
**Surface risks and unknowns**
- Identify what could go wrong
- Find gaps in understanding
- Suggest spikes or investigations
---
## OpenSpec Awareness
You have full context of the OpenSpec system. Use it naturally, don't force it.
### Check for context
At the start, quickly check what exists:
```bash
openspec list --json
```
This tells you:
- If there are active changes
- Their names, schemas, and status
- What the user might be working on
### When no change exists
Think freely. When insights crystallize, you might offer:
- "This feels solid enough to start a change. Want me to create a proposal?"
- Or keep exploring - no pressure to formalize
### When a change exists
If the user mentions a change or you detect one is relevant:
1. **Read existing artifacts for context**
- `openspec/changes/<name>/proposal.md`
- `openspec/changes/<name>/design.md`
- `openspec/changes/<name>/tasks.md`
- etc.
2. **Reference them naturally in conversation**
- "Your design mentions using Redis, but we just realized SQLite fits better..."
- "The proposal scopes this to premium users, but we're now thinking everyone..."
3. **Offer to capture when decisions are made**
| Insight Type | Where to Capture |
|--------------|------------------|
| New requirement discovered | `specs/<capability>/spec.md` |
| Requirement changed | `specs/<capability>/spec.md` |
| Design decision made | `design.md` |
| Scope changed | `proposal.md` |
| New work identified | `tasks.md` |
| Assumption invalidated | Relevant artifact |
Example offers:
- "That's a design decision. Capture it in design.md?"
- "This is a new requirement. Add it to specs?"
- "This changes scope. Update the proposal?"
4. **The user decides** - Offer and move on. Don't pressure. Don't auto-capture.
---
## What You Don't Have To Do
- Follow a script
- Ask the same questions every time
- Produce a specific artifact
- Reach a conclusion
- Stay on topic if a tangent is valuable
- Be brief (this is thinking time)
---
## Handling Different Entry Points
**User brings a vague idea:**
```
User: I'm thinking about adding real-time collaboration
You: Real-time collab is a big space. Let me think about this...
COLLABORATION SPECTRUM
════════════════════════════════════════════
Awareness Coordination Sync
│ │ │
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐
│Presence│ │Cursors │ │ CRDT │
│ "3 │ │ Multi │ │Conflict│
│online" │ │ select │ │ free │
└────────┘ └────────┘ └────────┘
│ │ │
trivial moderate complex
Where's your head at?
```
**User brings a specific problem:**
```
User: The auth system is a mess
You: [reads codebase]
┌─────────────────────────────────────────────┐
│ CURRENT AUTH FLOW │
└─────────────────────────────────────────────┘
┌─────────────┼─────────────┐
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ Google │ │ GitHub │ │ Email │
│ OAuth │ │ OAuth │ │ Magic │
└────┬────┘ └────┬────┘ └────┬────┘
│ │ │
└─────────────┼─────────────┘
┌───────────┐
│ Session │
└─────┬─────┘
┌───────────┐
│ Perms │
└───────────┘
I see three tangles. Which one's burning?
```
**User is stuck mid-implementation:**
```
User: /opsx:explore add-auth-system
The OAuth integration is more complex than expected
You: [reads change artifacts]
You're on task 4: "Implement OAuth flow"
Let me trace what's involved...
[draws diagram, explores options, suggests paths]
Want to update the design to reflect this?
Or add a spike task to investigate?
```
**User wants to compare options:**
```
User: Should we use Postgres or SQLite?
You: Generic answer is boring. What's the context?
User: A CLI tool that tracks local dev environments
You: That changes everything.
┌─────────────────────────────────────────────────┐
│ CLI TOOL DATA STORAGE │
└─────────────────────────────────────────────────┘
Key constraints:
• No daemon running
• Must work offline
• Single user
SQLite Postgres
Deployment embedded ✓ needs server ✗
Offline yes ✓ no ✗
Single file yes ✓ no ✗
SQLite. Not even close.
Unless... is there a sync component?
```
---
## Ending Discovery
There's no required ending. Discovery might:
- **Flow into a proposal**: "Ready to start? I can create a change proposal."
- **Result in artifact updates**: "Updated design.md with these decisions"
- **Just provide clarity**: User has what they need, moves on
- **Continue later**: "We can pick this up anytime"
When it feels like things are crystallizing, you might summarize:
```
## What We Figured Out
**The problem**: [crystallized understanding]
**The approach**: [if one emerged]
**Open questions**: [if any remain]
**Next steps** (if ready):
- Create a change proposal
- Keep exploring: just keep talking
```
But this summary is optional. Sometimes the thinking IS the value.
---
## Guardrails
- **Don't implement** - Never write code or implement features. Creating OpenSpec artifacts is fine, writing application code is not.
- **Don't fake understanding** - If something is unclear, dig deeper
- **Don't rush** - Discovery is thinking time, not task time
- **Don't force structure** - Let patterns emerge naturally
- **Don't auto-capture** - Offer to save insights, don't just do it
- **Do visualize** - A good diagram is worth many paragraphs
- **Do explore the codebase** - Ground discussions in reality
- **Do question assumptions** - Including the user's and your own

View file

@ -0,0 +1,110 @@
---
name: openspec-propose
description: Propose a new change with all artifacts generated in one step. Use when the user wants to quickly describe what they want to build and get a complete proposal with design, specs, and tasks ready for implementation.
license: MIT
compatibility: Requires openspec CLI.
metadata:
author: openspec
version: "1.0"
generatedBy: "1.2.0"
---
Propose a new change - create the change and generate all artifacts in one step.
I'll create a change with artifacts:
- proposal.md (what & why)
- design.md (how)
- tasks.md (implementation steps)
When ready to implement, run /opsx:apply
---
**Input**: The user's request should include a change name (kebab-case) OR a description of what they want to build.
**Steps**
1. **If no clear input provided, ask what they want to build**
Use the **AskUserQuestion tool** (open-ended, no preset options) to ask:
> "What change do you want to work on? Describe what you want to build or fix."
From their description, derive a kebab-case name (e.g., "add user authentication" → `add-user-auth`).
**IMPORTANT**: Do NOT proceed without understanding what the user wants to build.
2. **Create the change directory**
```bash
openspec new change "<name>"
```
This creates a scaffolded change at `openspec/changes/<name>/` with `.openspec.yaml`.
3. **Get the artifact build order**
```bash
openspec status --change "<name>" --json
```
Parse the JSON to get:
- `applyRequires`: array of artifact IDs needed before implementation (e.g., `["tasks"]`)
- `artifacts`: list of all artifacts with their status and dependencies
4. **Create artifacts in sequence until apply-ready**
Use the **TodoWrite tool** to track progress through the artifacts.
Loop through artifacts in dependency order (artifacts with no pending dependencies first):
a. **For each artifact that is `ready` (dependencies satisfied)**:
- Get instructions:
```bash
openspec instructions <artifact-id> --change "<name>" --json
```
- The instructions JSON includes:
- `context`: Project background (constraints for you - do NOT include in output)
- `rules`: Artifact-specific rules (constraints for you - do NOT include in output)
- `template`: The structure to use for your output file
- `instruction`: Schema-specific guidance for this artifact type
- `outputPath`: Where to write the artifact
- `dependencies`: Completed artifacts to read for context
- Read any completed dependency files for context
- Create the artifact file using `template` as the structure
- Apply `context` and `rules` as constraints - but do NOT copy them into the file
- Show brief progress: "Created <artifact-id>"
b. **Continue until all `applyRequires` artifacts are complete**
- After creating each artifact, re-run `openspec status --change "<name>" --json`
- Check if every artifact ID in `applyRequires` has `status: "done"` in the artifacts array
- Stop when all `applyRequires` artifacts are done
c. **If an artifact requires user input** (unclear context):
- Use **AskUserQuestion tool** to clarify
- Then continue with creation
5. **Show final status**
```bash
openspec status --change "<name>"
```
**Output**
After completing all artifacts, summarize:
- Change name and location
- List of artifacts created with brief descriptions
- What's ready: "All artifacts created! Ready for implementation."
- Prompt: "Run `/opsx:apply` or ask me to implement to start working on the tasks."
**Artifact Creation Guidelines**
- Follow the `instruction` field from `openspec instructions` for each artifact type
- The schema defines what each artifact should contain - follow it
- Read dependency artifacts for context before creating new ones
- Use `template` as the structure for your output file - fill in its sections
- **IMPORTANT**: `context` and `rules` are constraints for YOU, not content for the file
- Do NOT copy `<context>`, `<rules>`, `<project_context>` blocks into the artifact
- These guide what you write, but should never appear in the output
**Guardrails**
- Create ALL artifacts needed for implementation (as defined by schema's `apply.requires`)
- Always read dependency artifacts before creating a new one
- If context is critically unclear, ask the user - but prefer making reasonable decisions to keep momentum
- If a change with that name already exists, ask if user wants to continue it or create a new one
- Verify each artifact file exists after writing before proceeding to next

View file

@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-05-11

View file

@ -0,0 +1,250 @@
## Context
当前有多台机器WSL2 workstation、MacBook、可能的云服务器运行不同类型的 AI Agent
- **OpenClaw**Jeeves orchestrator + 多个 sub-agent
- **Claude Code**:本地 CLI 编码
- **Codex CLI**OpenAI 编码
- **Hermes Agent**:其他类型
- **ACP-compatible agents**Devin 等
现状Agent 之间无统一协同机制,任务靠人工传递,进度靠人工追踪,没有结构化的完成验证。
已有基础设施:
- **Matrix**0x08.org homeserver 已运行
- **Forgejo**:需要部署(建议自建,或用 Gitea 替代)
- 各机器可以互相网络通信
## Goals / Non-Goals
**Goals:**
- 建立统一的 Agent 编排平台,支持任意类型 Agent 加入
- Forgejo Issue/PR 作为任务事实来源,人类和 Agent 共用同一界面
- Matrix 作为实时协同层,提供 ChatOps 和通知
- 结构化 receipt 协议,不信任模型口头声明
- 最小化对现有 Agent 的侵入性adapter 模式)
- 可扩展:新 Agent 类型只需实现 adapter 即可接入
**Non-Goals:**
- 不做 Agent 自身的改进Agent 内部行为不在 scope 内)
- 不做 IDE 集成VS Code / JetBrains 插件)
- 不做 LLM provider 管理(使用各 Agent 自己的 provider 配置)
- 不做前端 Web UIPhase 1 用 Forgejo + Matrix 作为 UI
- 不替换 cc-connect / cc-telegram-bridge它们可以作为 adapter 接入)
## Decisions
### Decision 1: Forgejo而非 Gitea作为 Git 平台
**选择**: Forgejo
**理由**:
- Forgejo 是 Gitea 的社区 fork治理更开放
- 内置 CI/CDForgejo Actions未来可扩展
- API 兼容 Gitea迁移成本低
- 支持 F3 (Friendly Forge Format),数据可移植
**替代方案**:
- Gitea更成熟但治理有争议公司化
- GitHub不方便自建网络可达性差
- GitLab太重资源消耗大
### Decision 2: Orchestrator 用 Rust + zigbuild
**选择**: Rust + cargo-zigbuild交叉编译
**理由**:
- 内存安全:无 GC、无 data race、无 null pointer
- 单二进制部署zigbuild 交叉编译,无 libc 兼容性问题
- 性能:原生性能,适合长运行服务
- 类型系统:强类型 + algebraic data types适合状态机建模
- 生态reqwestHTTP、matrix-sdkMatrix、rusqliteSQLite、serdeJSON/TOML
- 交叉编译cargo-zigbuild 一行命令产出 Linux/macOS/Windows 二进制
**替代方案**:
- TypeScript (Node.js):开发快但需要运行时,非单二进制
- Go单二进制但内存安全不如 Rust交叉编译有 libc 问题
### Decision 3: Agent-Orchestrator 通信用 HTTP APIaxum
**选择**: Agent 通过 HTTP API 与 Orchestrator 通信Orchestrator 端用 axum 框架
**理由**:
- 跨语言、跨平台:任何 Agent 都能发 HTTP 请求
- 防火墙友好
- 与 Forgejo webhook 统一协议栈
- axum 是 Rust 生态最成熟的 async HTTP 框架
**替代方案**:
- WebSocket实时性好但复杂度高重连逻辑麻烦
- gRPC性能好但 Agent 端实现门槛高
- Message QueueNATS/Redis增加基础设施依赖
### Decision 4: Event sourcing 作为审计基础rusqlite
**选择**: 所有状态变更作为不可变事件 append 到 SQLite通过 rusqlite 访问
**理由**:
- 完整审计追踪
- 可重放
- 轻量,不需要外部数据库,适合单二进制打包
- rusqlite 是 Rust 生态最成熟的 SQLite 绑定
- 适合中小规模 Agent 舰队(< 100 agents
**替代方案**:
- PostgreSQL强大但引入运维复杂度破坏单二进制部署
- JSON 文件:简单但无查询能力
- 只记录当前状态:无法审计
### Decision 5: Adapter 模式接入多类型 Agent
**选择**: 定义统一 adapter interface各 Agent 实现自己的 adapter
**理由**:
- 最小侵入Agent 不需要改内部逻辑
- 可扩展:新 Agent 类型只需写 adapter
- 隔离adapter 故障不影响 Orchestrator
**adapter 执行方式**:
- Claude Code adapterspawn `claude -p` 子进程
- Codex adapterspawn `codex exec` 子进程
- OpenClaw adapter调用 gateway HTTP API
- ACP adapter通过 ACP 协议 WebSocket
- Shell adapter执行任意 shell 命令(最通用)
### Decision 6: 配置用 TOML
**选择**: TOML与 cc-connect 一致)
**理由**:
- 人类可读性好
- 类型比 YAML 更明确
- cc-connect 已验证
## Risks / Trade-offs
### Risk: Agent 执行环境差异
不同机器上的 Agent 运行环境OS、依赖、权限不同可能导致同一任务在不同 Agent 上行为不一致。
**Mitigation**: adapter 负责环境检查任务描述尽量环境无关receipt 验证在 Forgejo 侧(与执行环境解耦)。
### Risk: Orchestrator 单点故障
Orchestrator 挂了,整个舰队停摆。
**Mitigation**: Phase 1 接受单点Orchestrator 做到无状态(状态在 SQLite + Forgejo快速重启恢复。
### Risk: Forgejo webhook 延迟或丢失
网络抖动可能导致 webhook 丢失。
**Mitigation**: Orchestrator 定期轮询 Forgejo 做对账reconciliation弥补 webhook 丢失。
### Risk: Agent 心跳风暴
大量 Agent 同时发心跳可能导致 Orchestrator 负载过高。
**Mitigation**: 心跳间隔可配置(默认 60sOrchestrator 做好限流。
### Trade-off: 简单性 vs 实时性
选择 HTTP 而非 WebSocket/MQ 意味着实时性稍差。
→ 对于任务编排场景秒级延迟完全可接受。Matrix 通知提供实时感。
## Architecture Overview
```
┌─────────────┐ webhook ┌──────────────────┐
│ Forgejo │ ───────────────→ │ Orchestrator │
│ (Git+Issue) │ ←─── API ────── │ (Node.js) │
└─────────────┘ │ │
│ - Agent Registry │
┌─────────────┐ HTTP API │ - Task Router │
│ Matrix │ ←──────────────→│ - Event Log │
│ (ChatOps) │ │ - Receipt Validator│
└─────────────┘ └────────┬──────────┘
│ HTTP API
┌───────────────────┼───────────────────┐
│ │ │
┌──────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐
│ Adapter A │ │ Adapter B │ │ Adapter C │
│ Claude Code │ │ Codex CLI │ │ OpenClaw │
│ (host-01) │ │ (host-02) │ │ (host-03) │
└─────────────┘ └─────────────┘ └─────────────┘
```
## Data Model (Core)
```typescript
interface Agent {
agent_id: string;
agent_type: "openclaw" | "claude-code" | "codex-cli" | "hermes" | "acp" | "shell";
hostname: string;
capabilities: string[];
max_concurrency: number;
current_tasks: number;
status: "online" | "offline" | "draining";
last_heartbeat_at: string; // ISO 8601
registered_at: string;
metadata: Record<string, string>;
}
interface Task {
task_id: string;
source: string; // "forgejo:<repo>#<issue>"
type: string; // from label: "code", "review", "test", "deploy", "research"
priority: "low" | "normal" | "high" | "urgent";
status: TaskStatus;
assigned_agent_id?: string;
requirements: string; // Issue body
labels: string[];
created_at: string;
assigned_at?: string;
started_at?: string;
completed_at?: string;
retry_count: number;
max_retries: number;
timeout_seconds: number;
}
type TaskStatus = "created" | "assigned" | "running" | "completed" | "failed" | "agent_lost" | "cancelled";
interface Receipt {
task_id: string;
agent_id: string;
status: "completed" | "failed" | "partial";
duration_seconds: number;
summary: string;
artifacts: Artifact[];
error?: string;
}
interface Artifact {
type: "pr" | "commit" | "file" | "comment" | "url";
url?: string;
path?: string;
description?: string;
}
interface TaskEvent {
event_id: string;
task_id: string;
event_type: string; // "created", "assigned", "started", "receipt_submitted", "completed", "failed", ...
agent_id?: string;
timestamp: string;
payload: Record<string, unknown>;
}
```
## Migration Plan
1. **部署 Forgejo**:自建实例,配置 webhook
2. **部署 Orchestrator**Node.js 进程,连接 Forgejo + Matrix
3. **实现 Claude Code adapter**:第一个 adapter验证端到端流程
4. **实现 Codex adapter**:第二个 adapter
5. **实现 OpenClaw adapter**:第三个 adapter可选 Phase 2
6. **逐步迁移现有任务到 Forgejo Issue**
### Rollback
- Orchestrator 可随时停止,不影响 Forgejo 和 Matrix
- Agent 可独立运行(只是没有编排)
- 所有状态在 Forgejo Issue + SQLite可手动接管
## Open Questions
1. ~~**Forgejo 部署位置**~~:✅ 已部署在 arm0.0x08.org域名 git.0x08.org
2. **Orchestrator 部署位置**TBDarm0 / WSL2 / 独立机器)
3. **Agent 工作目录策略**:每个任务 clone 新 worktree 还是共享 workspace
4. **权限模型**Issue comment 中的 `/assign` 命令是否需要权限控制?
5. **cc-connect 集成**:✅ 放 Phase 2

View file

@ -0,0 +1,37 @@
## Why
多台机器上运行着不同类型的 AI AgentOpenClaw、Claude Code、Codex、Hermes Agent 等目前缺乏统一的跨机任务编排与协同机制。Agent 之间只能靠人工传递上下文,无法自动分发任务、追踪进度、回写结果。需要一个 **agent-fleet platform**,让任意类型的 Agent 通过统一的协议加入舰队,接收任务、汇报状态、协同完成复杂工程。
## What Changes
- **引入 Git 仓库Forgejo作为任务事实来源**Issue = 任务单元PR = 交付物Label/Milestone = 分类与排期
- **引入实时协同层**Matrix 作为 ChatOps 通道Agent 状态变更、任务分配、完成通知等通过 Matrix 房间实时推送
- **建立 Agent Registry**:每台机器上的 Agent 启动时向 Registry 注册(类型、能力、负载),支持动态发现与路由
- **建立 Task Router**Orchestrator 根据 Issue 类型、Agent 能力、负载状态,自动将任务路由到合适的 Agent
- **建立结构化 Receipt 协议**Agent 完成工作后回写结构化 receiptIssue comment / PR / Matrix 通知),系统不信任模型口头声明
- **支持多 Agent 类型**OpenClaw、Claude Code、Codex CLI、Hermes Agent、任意 ACP-compatible agent只要能读写 Git repo 并发 Matrix 消息即可加入
- **支持 hooks/webhook**Forgejo webhook → 路由到编排层 → 触发 Agent 执行
## Capabilities
### New Capabilities
- `agent-registry`: Agent 注册、心跳、能力声明、动态发现。每台机器上的 Agent 启动时注册自身类型、hostname、能力标签、当前负载Orchestrator 据此做任务路由
- `task-router`: 任务解析与分发。从 Forgejo Issue/PR 事件中解析任务需求,匹配 Agent 能力与负载,生成执行指令并投递
- `receipt-protocol`: 结构化完成回执。Agent 完成工作后必须回写结构化 receiptIssue comment / PR / Matrix 通知),系统据此判定完成状态,不依赖模型口头声明
- `forgejo-integration`: 与 Forgejo 的双向集成。监听 Issue/PR webhook 事件Agent 执行完成后回写 comment、创建 PR、更新 label/milestone
- `matrix-chatops`: Matrix 实时协同层。Agent 状态变更、任务分配、完成通知、人类审批等通过 Matrix 房间流转;支持 slash command 触发编排操作
- `agent-adapter`: 多类型 Agent 适配层。定义统一 adapter 接口,各类型 AgentOpenClaw、Claude Code、Codex CLI、Hermes Agent、ACP agent实现自己的 adapter接入统一编排
- `orchestrator-core`: 编排核心。管理任务生命周期created → assigned → running → completed/failed调度 Agent处理超时/重试/升级,维护全局状态
### Modified Capabilities
(初始项目,无既有 capability 需修改)
## Impact
- **新系统**:需要部署 Forgejo 实例 + Matrix homeserver或复用现有
- **网络**:各机器需要能访问 Forgejo APIHTTP、Matrix federationHTTPS、Orchestrator APIHTTP/WebSocket
- **Agent 端**:每种 Agent 需要实现 adapter最小要求能读 Git repo、能调用 Forgejo API 写 comment/PR、能发 Matrix 消息
- **依赖**ForgejoGit + Issue + PR + webhook、Matrix实时消息、Node.js/PythonOrchestrator runtime
- **运维**:需要 monitor Agent 心跳、任务超时、Forgejo webhook 健康检查

View file

@ -0,0 +1,41 @@
## ADDED Requirements
### Requirement: Unified adapter interface
系统 SHALL 定义统一的 Agent Adapter 接口,所有类型的 Agent 通过实现该接口接入编排系统。
Adapter 接口 SHALL 至少包含:
- `register()` — 注册到 Registry
- `heartbeat()` — 发送心跳
- `execute(task)` — 接收并执行任务
- `submit_receipt(receipt)` — 提交 receipt
- `deregister()` — 注销
#### Scenario: Claude Code adapter implementation
- **WHEN** 使用 Claude Code adapter
- **THEN** `execute(task)` SHALL 将任务 prompt 注入 `claude -p --output-format json`,在工作目录中执行,解析输出为 receipt
#### Scenario: Codex CLI adapter implementation
- **WHEN** 使用 Codex adapter
- **THEN** `execute(task)` SHALL 使用 `codex exec --json` 执行任务,解析输出为 receipt
#### Scenario: OpenClaw adapter implementation
- **WHEN** 使用 OpenClaw adapter
- **THEN** `execute(task)` SHALL 通过 OpenClaw gateway API 或 CLI 触发 agent 执行
#### Scenario: ACP-compatible agent adapter
- **WHEN** 使用 ACP adapter
- **THEN** `execute(task)` SHALL 通过 ACP 协议启动 agent session传递任务 prompt收集输出
### Requirement: Adapter configuration
每个 Agent 实例 SHALL 通过配置文件指定 adapter 类型、连接参数、工作目录、环境变量。
#### Scenario: Configuration file format
- **WHEN** Agent 实例配置为 Claude Code 类型
- **THEN** 配置文件 SHALL 包含:`{adapter: "claude-code", work_dir: "/path/to/repo", model: "sonnet", max_concurrency: 2, capabilities: ["code:typescript", "review"]}`
### Requirement: Adapter health check
Adapter SHALL 提供健康检查能力:检查底层 Agent 是否可用CLI 是否安装、API 是否可达)。
#### Scenario: Claude Code CLI not found
- **WHEN** Claude Code adapter 初始化时检测到 `claude` CLI 未安装
- **THEN** Adapter SHALL 返回健康检查失败Agent 注册 SHALL 被拒绝

View file

@ -0,0 +1,44 @@
## ADDED Requirements
### Requirement: Agent self-registration
每台机器上的 Agent 启动时 SHALL 向 Orchestrator Registry 注册自身信息agent_id、agent_typeopenclaw / claude-code / codex-cli / hermes / acp 等、hostname、capabilities能力标签列表、max_concurrency、metadata版本、工作目录等
#### Scenario: New agent starts and registers
- **WHEN** 一个新的 Codex CLI Agent 在 host-worker-02 上启动
- **THEN** 它 SHALL 调用 `POST /api/v1/agents/register`Orchestrator 记录该 Agent 信息并返回 agent_id 和 registry token
#### Scenario: Duplicate registration with same agent_id
- **WHEN** 已注册的 Agent 重启后再次注册(相同 agent_id
- **THEN** 系统 SHALL 更新该 Agent 的信息hostname、capabilities 等)而非创建重复条目
### Requirement: Agent heartbeat
已注册的 Agent SHALL 每隔可配置的间隔(默认 60 秒发送心跳。Orchestrator 据此判定 Agent 是否在线。
#### Scenario: Agent sends heartbeat on time
- **WHEN** Agent 在 60 秒内发送心跳
- **THEN** Orchestrator 更新 `last_heartbeat_at` 并保持 Agent 状态为 `online`
#### Scenario: Agent misses 3 consecutive heartbeats
- **WHEN** Agent 连续 3 个心跳周期未发送心跳180 秒)
- **THEN** Orchestrator SHALL 将该 Agent 状态标记为 `offline`,并将该 Agent 上所有 `running` 状态的任务标记为 `agent_lost`
### Requirement: Agent capability declaration
Agent 注册时 SHALL 声明自己的能力标签(如 `code:typescript``code:python``review``test``deploy``research`。Task Router 据此匹配任务。
#### Scenario: Task requiring specific capability
- **WHEN** 一个 Issue 被标记为 `agent:review` 且需要 TypeScript 能力
- **THEN** Task Router SHALL 只将其分配给声明了 `review``code:typescript` 能力的在线 Agent
### Requirement: Agent graceful deregistration
Agent 正常关闭时 SHALL 调用 `POST /api/v1/agents/deregister`Orchestrator 将其标记为 `offline`
#### Scenario: Agent deregisters on shutdown
- **WHEN** Agent 调用 deregister API
- **THEN** Orchestrator SHALL 将该 Agent 状态设为 `offline`,该 Agent 上所有 `running` 任务 SHALL 被重新入队
### Requirement: Agent list and query
Orchestrator SHALL 提供 API 查询当前所有注册 Agent 的状态、能力、负载。
#### Scenario: Query agents by capability
- **WHEN** 调用 `GET /api/v1/agents?capability=code:python&status=online`
- **THEN** 返回所有在线且声明了 `code:python` 能力的 Agent 列表

View file

@ -0,0 +1,44 @@
## ADDED Requirements
### Requirement: Webhook endpoint for Forgejo
Orchestrator SHALL 暴露 HTTP webhook endpoint 接收 Forgejo 事件:`POST /api/v1/webhooks/forgejo`
#### Scenario: Forgejo sends issue event
- **WHEN** Forgejo 配置了指向 Orchestrator 的 webhookIssue 事件触发
- **THEN** Orchestrator SHALL 接收、验证签名、解析事件体,并路由到 Task Router
#### Scenario: Invalid webhook signature
- **WHEN** 收到的 webhook 签名验证失败
- **THEN** Orchestrator SHALL 返回 401 并记录安全日志
### Requirement: Issue to task conversion
Orchestrator SHALL 将 Forgejo Issue 转换为内部任务保持双向映射Issue URL ↔ task_id。
#### Scenario: Issue created with agent label
- **WHEN** Issue #42 在 repo `my-project` 中创建,带 `agent:code` 标签
- **THEN** 创建任务,`source = "forgejo:my-project#42"`,任务状态为 `created`
### Requirement: Task status sync back to Issue
任务状态变更 SHALL 同步回 Forgejo Issuelabel 更新(`status:todo``status:doing``status:done`、milestone 更新、assignee 更新。
#### Scenario: Task assigned to agent
- **WHEN** 任务被分配给 Agent `worker-03`
- **THEN** 对应 Issue 的 assignee SHALL 更新为 `worker-03` 对应的 Forgejo 用户label SHALL 添加 `status:doing`
#### Scenario: Task completed
- **WHEN** 任务状态变为 `completed`
- **THEN** Issue label SHALL 从 `status:doing` 变为 `status:done`Issue comment SHALL 写入 receipt summary
### Requirement: PR creation and update
Agent 通过 Orchestrator 创建的 PR SHALL 关联到原始 Issue通过 description 或 `Closes #N` 引用)。
#### Scenario: Agent creates PR via Orchestrator
- **WHEN** Agent 在 receipt 中声明需要创建 PR
- **THEN** Orchestrator SHALL 协助创建 PR或验证 Agent 直接创建的 PR确保 PR body 包含 `Closes #<issue-number>`
### Requirement: Forgejo API authentication
Orchestrator SHALL 使用 Forgejo API token 进行所有 API 调用(读取 Issue、创建 comment、更新 label、创建 PR 等)。
#### Scenario: Token rotation
- **WHEN** Forgejo API token 过期
- **THEN** Orchestrator SHALL 返回明确错误并通过 Matrix 通知管理员

View file

@ -0,0 +1,45 @@
## ADDED Requirements
### Requirement: Matrix room as coordination channel
Orchestrator SHALL 使用 Matrix 房间作为实时协同通道Agent 状态变更、任务分配、完成通知、人类审批等事件 SHALL 推送到 Matrix。
#### Scenario: Task assigned notification
- **WHEN** 任务 #42 被分配给 Agent `worker-03`
- **THEN** Matrix 协同房间 SHALL 收到通知:`📋 #42 → worker-03 [code:typescript]`
#### Scenario: Agent offline alert
- **WHEN** Agent `worker-03` 连续 3 次心跳失败
- **THEN** Matrix 房间 SHALL 收到告警:`⚠️ worker-03 offline — 2 running tasks affected`
### Requirement: Slash commands for orchestration
人类 SHALL 能通过 Matrix slash command 触发编排操作。
#### Scenario: /fleet status
- **WHEN** 人类发送 `/fleet status`
- **THEN** Bot SHALL 回复所有 Agent 当前状态表格Agent ID、类型、状态、当前任务数、能力
#### Scenario: /assign command
- **WHEN** 人类发送 `/assign worker-03 #42`
- **THEN** 任务 #42 SHALL 被手动分配给 worker-03
#### Scenario: /retry command
- **WHEN** 人类发送 `/retry #42`
- **THEN** 失败的任务 #42 SHALL 被重新入队
### Requirement: Matrix notifications for receipts
每个 receipt 回写 SHALL 触发 Matrix 通知包含任务状态、摘要、artifact 链接。
#### Scenario: Task completed notification
- **WHEN** 任务 #42 的 receipt 验证通过,状态为 `completed`
- **THEN** Matrix 房间 SHALL 收到通知:`✅ #42 completed by worker-03 — PR #15 — "修复登录验证 bug"`
#### Scenario: Task failed notification
- **WHEN** 任务 #42 失败
- **THEN** Matrix 房间 SHALL 收到通知:`❌ #42 failed — worker-03 — "构建超时"`
### Requirement: Per-agent Matrix thread
每个 Agent SHALL 有独立的 Matrix thread或 topic用于该 Agent 的执行日志、状态更新、调试输出。
#### Scenario: Agent execution log
- **WHEN** Agent worker-03 开始执行任务 #42
- **THEN** worker-03 的 thread SHALL 收到执行开始消息,后续日志更新也在此 thread

View file

@ -0,0 +1,44 @@
## ADDED Requirements
### Requirement: Task lifecycle state machine
Orchestrator SHALL 维护任务的状态机:`created``assigned``running``completed` / `failed` / `agent_lost` / `cancelled`。每次状态转换 SHALL 记录时间戳和触发原因。
#### Scenario: Full happy path
- **WHEN** Issue 创建 → Agent 匹配 → Agent 接受 → 执行完成 → Receipt 验证通过
- **THEN** 状态 SHALL 按序流转:`created``assigned``running``completed`
#### Scenario: Agent lost during execution
- **WHEN** 执行中的 Agent 心跳超时,状态变为 `offline`
- **THEN** 任务状态 SHALL 变为 `agent_lost`Task Router SHALL 根据策略决定重新入队或标记 `failed`
### Requirement: Task timeout handling
任务 SHALL 有可配置的超时时间(默认 30 分钟)。超时后 SHALL 自动标记为 `failed`
#### Scenario: Task exceeds timeout
- **WHEN** 任务 #42 执行超过 30 分钟无 receipt
- **THEN** 任务 SHALL 标记为 `failed`reason 为 `timeout`Issue comment 写入超时通知
### Requirement: Task retry policy
失败的任务 SHALL 根据可配置的重试策略(最大重试次数、退避间隔)自动或手动重试。
#### Scenario: Auto-retry on transient failure
- **WHEN** 任务因 `agent_lost` 失败,重试策略允许最多 2 次自动重试
- **THEN** 任务 SHALL 重新入队,分配给下一个可用 Agent
#### Scenario: Max retries exceeded
- **WHEN** 任务已重试 2 次仍失败
- **THEN** 任务 SHALL 保持 `failed` 状态Matrix SHALL 通知人工介入
### Requirement: Global task queue
Orchestrator SHALL 维护全局任务队列,按优先级排序。高优先级任务 SHALL 优先分配。
#### Scenario: Priority ordering
- **WHEN** 队列中有 `priority:low` 任务 #10`priority:high` 任务 #42
- **THEN** 任务 #42 SHALL 先于 #10 被分配
### Requirement: Event sourcing for audit
所有任务状态转换、Agent 事件、receipt 提交 SHALL 作为不可变事件记录到 event log。
#### Scenario: Task history query
- **WHEN** 查询任务 #42 的历史
- **THEN** 返回完整的事件序列created → assigned to worker-03 → running → receipt submitted → completed每条带时间戳

View file

@ -0,0 +1,41 @@
## ADDED Requirements
### Requirement: Structured receipt format
Agent 完成任务后 SHALL 回写结构化 receipt。Receipt 包含task_id、agent_id、statuscompleted / failed / partial、duration_seconds、summary、artifactsPR URL、文件路径等、error失败时
#### Scenario: Successful task completion with PR
- **WHEN** Agent 完成代码任务并创建了 PR #15
- **THEN** Agent SHALL 提交 receipt`{status: "completed", artifacts: [{type: "pr", url: "https://forgejo.example/repo/pulls/15"}], summary: "..."}`
#### Scenario: Partial completion
- **WHEN** Agent 完成了部分工作但未能全部完成
- **THEN** Agent SHALL 提交 receipt`{status: "partial", summary: "完成 3/5 个文件修改test_auth.ts 超时", artifacts: [...]}`
### Requirement: Receipt delivery channels
Receipt SHALL 通过至少一个持久化渠道回写Forgejo Issue comment必须+ Matrix 通知(可选)。
#### Scenario: Receipt written as Issue comment
- **WHEN** Agent 提交 receipt
- **THEN** Orchestrator SHALL 在对应 Issue 下创建结构化 comment包含 status emoji + summary + artifact links
#### Scenario: Receipt triggers Matrix notification
- **WHEN** Receipt 写入成功
- **THEN** Orchestrator SHALL 向 Matrix 协同房间发送通知消息,包含任务状态和关键信息
### Requirement: Receipt validation
Orchestrator SHALL 验证 receipt 中的 artifact 声明(如 PR 是否真实存在)。
#### Scenario: PR artifact validation
- **WHEN** Receipt 声明创建了 PR #15
- **THEN** Orchestrator SHALL 通过 Forgejo API 验证 PR #15 确实存在,若不存在 SHALL 将任务标记为 `failed` 并通知 Agent
#### Scenario: Comment artifact validation
- **WHEN** Receipt 声明在某个文件中做了修改
- **THEN** Orchestrator SHALL 验证对应 commit/PR 包含该修改
### Requirement: No-trust policy
系统 SHALL NOT 仅凭 Agent 的文本输出判定任务完成。只有结构化 receipt + artifact 验证通过才算 `completed`
#### Scenario: Agent says done without receipt
- **WHEN** Agent 在 Matrix 发消息说"任务完成了"但未提交 receipt
- **THEN** 任务 SHALL 保持 `running` 状态,超时后按 `failed` 处理

View file

@ -0,0 +1,52 @@
## ADDED Requirements
### Requirement: Forgejo webhook event ingestion
Orchestrator SHALL 监听 Forgejo webhook 事件Issue 创建/更新/标签变更、PR 创建/更新/合并、Push 等),解析为内部任务事件。
#### Scenario: New issue with agent label
- **WHEN** Forgejo 上创建了新 Issue带有 `agent:code` 标签
- **THEN** Orchestrator SHALL 接收到 `issues` webhook 事件,解析为 `task.created` 事件,提取 Issue 编号、标题、描述、标签、仓库信息
#### Scenario: Issue label changed to trigger assignment
- **WHEN** Issue 的标签从 `agent:code` 变更为 `agent:review`
- **THEN** Orchestrator SHALL 生成 `task.reroute` 事件,重新匹配具备 `review` 能力的 Agent
### Requirement: Task parsing from Issue
Orchestrator SHALL 将 Issue 解析为结构化任务task_id、sourceforgejo issue URL、type由标签推断、priority由 label/milestone 推断、requirementsIssue body、labels。
#### Scenario: Issue with priority label
- **WHEN** Issue 带有 `priority:high` 标签和 `agent:code` 标签
- **THEN** 解析出的任务 SHALL 包含 `priority: "high"``type: "code"`
### Requirement: Agent matching and assignment
Task Router SHALL 根据任务类型、所需能力、Agent 负载和在线状态,将任务分配给最合适的 Agent。
#### Scenario: Match by capability and load
- **WHEN** 一个 `code:typescript` + `review` 类型的任务需要分配
- **THEN** Task Router SHALL 选择声明了对应能力、当前并发任务数未达上限、且状态为 `online` 的 Agent
#### Scenario: No matching agent available
- **WHEN** 没有在线 Agent 满足任务所需能力
- **THEN** 任务 SHALL 进入 `queued` 状态Task Router SHALL 通过 Matrix 通知人工介入
### Requirement: Task lifecycle management
任务 SHALL 具有明确的生命周期状态:`created``assigned``running``completed` / `failed` / `agent_lost`
#### Scenario: Task completes successfully
- **WHEN** Agent 通过 receipt 协议报告任务完成
- **THEN** 任务状态 SHALL 变更为 `completed`Issue 标签 SHALL 更新为 `status:done`
#### Scenario: Task fails with error
- **WHEN** Agent 报告任务失败,附带错误信息
- **THEN** 任务状态 SHALL 变更为 `failed`Issue comment SHALL 写入错误摘要Task Router SHALL 根据策略决定重试或升级
### Requirement: Manual task assignment
人类 SHALL 能通过 Matrix slash command 或 Forgejo Issue comment 手动指定任务分配给特定 Agent。
#### Scenario: Manual assignment via Matrix
- **WHEN** 人类在 Matrix 发送 `/assign @worker-03 issue#42`
- **THEN** Task Router SHALL 将 Issue #42 分配给 agent_id 为 `worker-03` 的 Agent无论自动匹配结果
#### Scenario: Manual assignment via Issue comment
- **WHEN** 人类在 Issue #42 评论 `/assign worker-03`
- **THEN** 效果同上

View file

@ -0,0 +1,82 @@
## 1. 项目脚手架与基础设施
- [ ] 1.1 初始化 Node.js 项目package.json、tsconfig.json、ESLint、Vitest
- [ ] 1.2 搭建项目目录结构src/core、src/adapters、src/integrations、src/api
- [ ] 1.3 部署 Forgejo 实例WSL2 或 Docker创建初始 repo 和 webhook token
- [ ] 1.4 配置 Matrix bot 账号(复用现有 @jeeves:0x08.org 或新建专用 bot
- [ ] 1.5 编写 config.toml schema 和示例配置文件
## 2. Orchestrator Core
- [ ] 2.1 实现数据模型Agent、Task、Receipt、Artifact、TaskEvent 类型定义
- [ ] 2.2 实现 Event StoreSQLite append-only event log写入和查询接口
- [ ] 2.3 实现 Task 状态机created → assigned → running → completed/failed/agent_lost/cancelled
- [ ] 2.4 实现全局任务队列:按优先级排序,支持入队/出队/重新入队
- [ ] 2.5 实现任务超时检测:定时扫描 running 任务,超时标记为 failed
- [ ] 2.6 实现重试策略:可配置 max_retries + 退避间隔,自动重试 transient failure
- [ ] 2.7 编写 Orchestrator Core 单元测试
## 3. Agent Registry
- [ ] 3.1 实现 `POST /api/v1/agents/register`Agent 注册,支持重复注册更新
- [ ] 3.2 实现 `POST /api/v1/agents/heartbeat`:心跳更新,记录 last_heartbeat_at
- [ ] 3.3 实现 `POST /api/v1/agents/deregister`:注销,重新入队该 Agent 的 running 任务
- [ ] 3.4 实现 `GET /api/v1/agents`:查询 Agent 列表,支持 capability 和 status 过滤
- [ ] 3.5 实现心跳超时检测后台定时扫描3 次超时标记 offline触发 agent_lost
- [ ] 3.6 编写 Agent Registry 单元测试
## 4. Forgejo Integration
- [ ] 4.1 实现 Forgejo API clientIssue CRUD、Comment、Label、PR、Webhook 验证
- [ ] 4.2 实现 `POST /api/v1/webhooks/forgejo`:接收 Forgejo webhook验证签名解析事件
- [ ] 4.3 实现 Issue → Task 转换:解析 label 推断 type/priority创建 Task 对象
- [ ] 4.4 实现 Task 状态 → Issue label 同步status:todo/doing/doneassignee 更新
- [ ] 4.5 实现 Receipt → Issue comment 回写:结构化 commentemoji + summary + artifact links
- [ ] 4.6 实现 Reconciliation对账定期轮询 Forgejo Issue弥补 webhook 丢失
- [ ] 4.7 编写 Forgejo Integration 单元测试和集成测试
## 5. Matrix ChatOps
- [ ] 5.1 实现 Matrix bot 连接:使用 matrix-bot-sdk连接 0x08.org homeserver
- [ ] 5.2 实现 `/fleet status` slash command展示所有 Agent 状态
- [ ] 5.3 实现 `/assign <agent> <issue>` slash command手动分配任务
- [ ] 5.4 实现 `/retry <issue>` slash command重新入队失败任务
- [ ] 5.5 实现通知推送task assigned、completed、failed、agent offline 等事件推送到协同房间
- [ ] 5.6 实现 per-agent thread每个 Agent 的执行日志发到独立 thread/topic
- [ ] 5.7 编写 Matrix ChatOps 单元测试
## 6. Receipt Protocol
- [ ] 6.1 实现 `POST /api/v1/receipts`:接收 Agent 提交的 receipt
- [ ] 6.2 实现 receipt validation验证 PR 是否存在Forgejo API 查询、commit 是否包含修改
- [ ] 6.3 实现 no-trust 检查:任务只在 receipt 验证通过后才变更为 completed
- [ ] 6.4 编写 Receipt Protocol 单元测试
## 7. Agent Adapter Interface
- [ ] 7.1 定义 adapter interface TypeScript 类型register/heartbeat/execute/submit_receipt/deregister
- [ ] 7.2 实现 adapter 配置加载:从 config.toml 读取各 Agent 实例的 adapter 类型和参数
- [ ] 7.3 实现 adapter health checkCLI 检查、API 可达性检查
- [ ] 7.4 实现 adapter runner管理 adapter 生命周期(启动、心跳、停止)
## 8. Claude Code Adapter第一个具体实现
- [ ] 8.1 实现 Claude Code adapterspawn `claude -p --output-format json`,注入 task prompt
- [ ] 8.2 解析 Claude Code JSON 输出为 receipt提取 PR、文件修改、summary
- [ ] 8.3 实现 workspace 管理:为每个任务创建/复用 git worktree
- [ ] 8.4 编写 Claude Code adapter 集成测试
## 9. Codex CLI Adapter第二个具体实现
- [ ] 9.1 实现 Codex adapterspawn `codex exec --json`,注入 task prompt
- [ ] 9.2 解析 Codex JSON 输出为 receipt
- [ ] 9.3 实现 Codex session resume可选
- [ ] 9.4 编写 Codex adapter 集成测试
## 10. 端到端验证
- [ ] 10.1 部署完整系统Forgejo + Orchestrator + Matrix bot + 1 个 Claude Code Agent
- [ ] 10.2 端到端测试:创建 Issue → webhook → 任务创建 → Agent 分配 → 执行 → Receipt → Issue comment → Matrix 通知
- [ ] 10.3 端到端测试Agent 离线 → 心跳超时 → 任务 agent_lost → 重新入队
- [ ] 10.4 端到端测试:任务超时 → 自动 failed → Matrix 通知
- [ ] 10.5 编写运维文档:部署、配置、排障