agent-orchestrator-kit 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/README.md +195 -7
- package/bin/agent-orchestrator.js +1212 -89
- package/package.json +2 -2
- package/profiles/generic/orchestrator.yaml +16 -0
- package/profiles/mvp/orchestrator.yaml +16 -0
- package/profiles/node/orchestrator.yaml +19 -1
- package/profiles/vue3/orchestrator.yaml +18 -1
- package/templates/.agents/amp.settings.json.example +12 -0
- package/templates/.agents/github.local.env.example +10 -0
- package/templates/.agents/gitlab.local.env.example +12 -0
- package/templates/.agents/mcp.json.example +12 -0
- package/templates/.agents/rules/memory-mcp-autosetup.mdc +1 -1
- package/templates/.agents/rules/session-handoff.mdc +7 -4
- package/templates/.agents/skills/agent-orchestration/SKILL.md +7 -3
- package/templates/.agents/subagents/session-handoff.md +7 -5
- package/templates/.cursor/memory.json +11 -0
- package/templates/orchestrator.yaml +16 -0
- package/templates/scripts/browser-mcp-launcher.cjs +21 -0
- package/templates/scripts/github-mcp-launcher.cjs +66 -0
- package/templates/scripts/gitlab-mcp-launcher.cjs +70 -0
- package/templates/scripts/pre-commit-gate-check.sh +4 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-orchestrator-kit",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Universal AI agent orchestration kit for Cursor, Claude Code, and Amp Code — spec-driven OpenSpec pipeline, conductor subagents, durable session handoff
|
|
3
|
+
"version": "0.5.0",
|
|
4
|
+
"description": "Universal AI agent orchestration kit for Cursor, Claude Code, and Amp Code — spec-driven OpenSpec pipeline, conductor subagents, durable session handoff, factory gates and MCP setup, cloud-agent handoff, and optional local Figma PAT setup",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai-agent",
|
|
7
7
|
"cursor",
|
|
@@ -61,6 +61,22 @@ mcp:
|
|
|
61
61
|
- memory
|
|
62
62
|
optional:
|
|
63
63
|
- figma
|
|
64
|
+
- github
|
|
65
|
+
- gitlab
|
|
66
|
+
- browser
|
|
67
|
+
|
|
68
|
+
skills:
|
|
69
|
+
kit:
|
|
70
|
+
- agent-orchestration
|
|
71
|
+
- openspec-howto
|
|
72
|
+
- openspec-explore
|
|
73
|
+
- openspec-propose
|
|
74
|
+
- openspec-apply-change
|
|
75
|
+
- openspec-archive-change
|
|
76
|
+
- openspec-sync-specs
|
|
77
|
+
- spec-workflow-openspec
|
|
78
|
+
stack: []
|
|
79
|
+
external: ""
|
|
64
80
|
|
|
65
81
|
figma:
|
|
66
82
|
env_file: .agents/figma.local.env
|
|
@@ -68,6 +68,22 @@ mcp:
|
|
|
68
68
|
- memory
|
|
69
69
|
optional:
|
|
70
70
|
- figma
|
|
71
|
+
- github
|
|
72
|
+
- gitlab
|
|
73
|
+
- browser
|
|
74
|
+
|
|
75
|
+
skills:
|
|
76
|
+
kit:
|
|
77
|
+
- agent-orchestration
|
|
78
|
+
- openspec-howto
|
|
79
|
+
- openspec-explore
|
|
80
|
+
- openspec-propose
|
|
81
|
+
- openspec-apply-change
|
|
82
|
+
- openspec-archive-change
|
|
83
|
+
- openspec-sync-specs
|
|
84
|
+
- spec-workflow-openspec
|
|
85
|
+
stack: []
|
|
86
|
+
external: ""
|
|
71
87
|
|
|
72
88
|
figma:
|
|
73
89
|
env_file: .agents/figma.local.env
|
|
@@ -36,7 +36,6 @@ roles:
|
|
|
36
36
|
command: /opsx:apply
|
|
37
37
|
mode: code
|
|
38
38
|
model_hint: strong
|
|
39
|
-
notes: "Use javascript-core, javascript-node, javascript-testing skills during apply"
|
|
40
39
|
verifier:
|
|
41
40
|
type: ci
|
|
42
41
|
gates:
|
|
@@ -66,6 +65,25 @@ mcp:
|
|
|
66
65
|
- memory
|
|
67
66
|
optional:
|
|
68
67
|
- figma
|
|
68
|
+
- github
|
|
69
|
+
- gitlab
|
|
70
|
+
- browser
|
|
71
|
+
|
|
72
|
+
skills:
|
|
73
|
+
kit:
|
|
74
|
+
- agent-orchestration
|
|
75
|
+
- openspec-howto
|
|
76
|
+
- openspec-explore
|
|
77
|
+
- openspec-propose
|
|
78
|
+
- openspec-apply-change
|
|
79
|
+
- openspec-archive-change
|
|
80
|
+
- openspec-sync-specs
|
|
81
|
+
- spec-workflow-openspec
|
|
82
|
+
stack:
|
|
83
|
+
- javascript-core
|
|
84
|
+
- javascript-node
|
|
85
|
+
- javascript-testing
|
|
86
|
+
external: frontend-agent-skills
|
|
69
87
|
|
|
70
88
|
figma:
|
|
71
89
|
env_file: .agents/figma.local.env
|
|
@@ -36,7 +36,6 @@ roles:
|
|
|
36
36
|
command: /opsx:apply
|
|
37
37
|
mode: code
|
|
38
38
|
model_hint: strong
|
|
39
|
-
notes: "Use vue-core, vue-pinia, vue-axios, vue-router skills during apply"
|
|
40
39
|
verifier:
|
|
41
40
|
type: ci
|
|
42
41
|
gates:
|
|
@@ -66,8 +65,26 @@ mcp:
|
|
|
66
65
|
optional:
|
|
67
66
|
- figma
|
|
68
67
|
- github
|
|
68
|
+
- gitlab
|
|
69
69
|
- browser
|
|
70
70
|
|
|
71
|
+
skills:
|
|
72
|
+
kit:
|
|
73
|
+
- agent-orchestration
|
|
74
|
+
- openspec-howto
|
|
75
|
+
- openspec-explore
|
|
76
|
+
- openspec-propose
|
|
77
|
+
- openspec-apply-change
|
|
78
|
+
- openspec-archive-change
|
|
79
|
+
- openspec-sync-specs
|
|
80
|
+
- spec-workflow-openspec
|
|
81
|
+
stack:
|
|
82
|
+
- vue-core
|
|
83
|
+
- vue-pinia
|
|
84
|
+
- vue-axios
|
|
85
|
+
- vue-router
|
|
86
|
+
external: frontend-agent-skills
|
|
87
|
+
|
|
71
88
|
figma:
|
|
72
89
|
env_file: .agents/figma.local.env
|
|
73
90
|
token_key: FIGMA_ACCESS_TOKEN
|
|
@@ -7,6 +7,18 @@
|
|
|
7
7
|
"figma": {
|
|
8
8
|
"command": "node",
|
|
9
9
|
"args": ["scripts/figma-mcp-launcher.cjs"]
|
|
10
|
+
},
|
|
11
|
+
"github": {
|
|
12
|
+
"command": "node",
|
|
13
|
+
"args": ["scripts/github-mcp-launcher.cjs"]
|
|
14
|
+
},
|
|
15
|
+
"gitlab": {
|
|
16
|
+
"command": "node",
|
|
17
|
+
"args": ["scripts/gitlab-mcp-launcher.cjs"]
|
|
18
|
+
},
|
|
19
|
+
"browser": {
|
|
20
|
+
"command": "node",
|
|
21
|
+
"args": ["scripts/browser-mcp-launcher.cjs"]
|
|
10
22
|
}
|
|
11
23
|
}
|
|
12
24
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# GitHub Personal Access Token (local only — never commit this file)
|
|
2
|
+
# Create: GitHub → Settings → Developer settings → Personal access tokens
|
|
3
|
+
# Recommended scopes: repo (private) or public_repo, plus pull requests as needed
|
|
4
|
+
#
|
|
5
|
+
# 1. Copy: cp .agents/github.local.env.example .agents/github.local.env
|
|
6
|
+
# 2. Paste your token below (do NOT paste it into AI chat)
|
|
7
|
+
# 3. Restart Cursor / Amp after saving
|
|
8
|
+
# 4. Check: npx agent-orchestrator-kit status
|
|
9
|
+
|
|
10
|
+
GITHUB_PERSONAL_ACCESS_TOKEN=
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# GitLab Personal Access Token (local only — never commit this file)
|
|
2
|
+
# Create: GitLab → Preferences → Access Tokens (api or read_api as needed)
|
|
3
|
+
# Self-hosted: set GITLAB_API_URL to https://<hostname>/api/v4
|
|
4
|
+
# mcp-setup writes GITLAB_API_URL from git remote origin when it detects GitLab
|
|
5
|
+
#
|
|
6
|
+
# 1. Copy: cp .agents/gitlab.local.env.example .agents/gitlab.local.env
|
|
7
|
+
# 2. Paste your token below (do NOT paste it into AI chat)
|
|
8
|
+
# 3. Restart Cursor / Amp after saving
|
|
9
|
+
# 4. Check: npx agent-orchestrator-kit status
|
|
10
|
+
|
|
11
|
+
GITLAB_PERSONAL_ACCESS_TOKEN=
|
|
12
|
+
GITLAB_API_URL=
|
|
@@ -7,6 +7,18 @@
|
|
|
7
7
|
"figma": {
|
|
8
8
|
"command": "node",
|
|
9
9
|
"args": ["scripts/figma-mcp-launcher.cjs"]
|
|
10
|
+
},
|
|
11
|
+
"github": {
|
|
12
|
+
"command": "node",
|
|
13
|
+
"args": ["scripts/github-mcp-launcher.cjs"]
|
|
14
|
+
},
|
|
15
|
+
"gitlab": {
|
|
16
|
+
"command": "node",
|
|
17
|
+
"args": ["scripts/gitlab-mcp-launcher.cjs"]
|
|
18
|
+
},
|
|
19
|
+
"browser": {
|
|
20
|
+
"command": "node",
|
|
21
|
+
"args": ["scripts/browser-mcp-launcher.cjs"]
|
|
10
22
|
}
|
|
11
23
|
}
|
|
12
24
|
}
|
|
@@ -9,4 +9,4 @@ If `.mcp.json` / `.amp/settings.json` lacks `memory`, or `MEMORY_FILE_PATH` is r
|
|
|
9
9
|
|
|
10
10
|
Use `node scripts/memory-mcp-launcher.cjs` (no relative `MEMORY_FILE_PATH`). Shared file: `.cursor/memory.json` (gitignored). Do not delete other MCP servers.
|
|
11
11
|
|
|
12
|
-
Entities: `Change:<name>` (status, tasks n/m, last_role, review) · `Handoff:<name>` (next_role, next_command, session_count, summary, blocked) · `Decision:<topic>` (chosen, reason). Writer: `npx agent-orchestrator-kit handoff <name
|
|
12
|
+
Entities: `Change:<name>` (status, tasks n/m, last_role, review) · `Handoff:<name>` (next_role, next_command, session_count, summary, blocked) · `Decision:<topic>` (chosen, reason) — mirror of git-tracked `openspec/changes/<name>/decisions.md` (file → Memory only; never Memory → file). Writer: `npx agent-orchestrator-kit handoff <name>` (same command appends `decisions.md`). Notify once: “Memory MCP connected.”
|
|
@@ -7,22 +7,25 @@ alwaysApply: true
|
|
|
7
7
|
|
|
8
8
|
This rule is the single source of the Session Start / Session Exit protocol. Commands reference it; they do not duplicate it. A `/opsx:*` session is incomplete without persist + the fenced next-thread prompt. FORBIDDEN until persist succeeds: done/готово, next phase, or omitting the prompt.
|
|
9
9
|
|
|
10
|
+
Agents (local or cloud) write session artifacts only to git-tracked paths — never `/tmp`, never gitignored caches.
|
|
11
|
+
|
|
10
12
|
## Session Start (before any work)
|
|
11
13
|
1. Honor pasted `/opsx:<phase> <name>` and announce the role.
|
|
12
14
|
2. `npx agent-orchestrator-kit status`
|
|
13
|
-
3. `npx agent-orchestrator-kit handoff --restore` (or `handoff <name> --restore`). The CLI briefing is canonical — it already reads memory.json and handoff.md;
|
|
15
|
+
3. `npx agent-orchestrator-kit handoff --restore` (or `handoff <name> --restore`). The CLI briefing is canonical — it already reads memory.json and handoff.md; accumulated decisions print from git-tracked `openspec/changes/<name>/decisions.md`, not from Memory. No separate Memory MCP read step.
|
|
14
16
|
4. If the restore CLI failed → read `openspec/changes/<name>/handoff.md` directly.
|
|
15
17
|
5. Spawn `session-handoff` in restore mode ONLY if both the CLI and handoff.md are unavailable (Amp: isolated `subagent-session-handoff`). This is a fallback, never a routine step.
|
|
16
18
|
6. Free-form continue/next/«далі» with one active change → execute `Handoff.next_command`.
|
|
17
19
|
7. Only then start phase work (spawn a specialist when the phase routing requires one).
|
|
18
20
|
|
|
19
21
|
## Session Exit (order)
|
|
20
|
-
1. The parent writes `openspec/changes/<name>/handoff.md` itself: Closed role, Change, Done, Decisions, Blocked, Next command, Next role, Attach, Subagents to spawn, Constraints.
|
|
21
|
-
2. `npx agent-orchestrator-kit handoff <name>` — require exit 0 (upserts absolute-path Memory JSON, prints the expanded prompt on stdout).
|
|
22
|
+
1. The parent writes `openspec/changes/<name>/handoff.md` itself: Closed role, Change, Done, Decisions, Blocked, Next command, Next role, Attach, Subagents to spawn, Constraints, Runtime.
|
|
23
|
+
2. `npx agent-orchestrator-kit handoff <name>` — require exit 0 (appends non-empty Decisions into append-only `openspec/changes/<name>/decisions.md`, upserts absolute-path Memory JSON, records the session into `openspec/changes/<name>/metrics.json`, prints the expanded prompt on stdout). `decisions.md` is the git canon of change decisions; Memory `Decision:*` is a file→Memory mirror only. Cloud sessions pass `--runtime cloud` (or set `AOK_RUNTIME=cloud` / `AOK_AGENT_ID` in the cloud-agent environment). When session spend is known, pass it to persist: `--model <name> --input-tokens <n> --output-tokens <n> --cost-usd <usd>` — metrics power planning; never guess values you do not know.
|
|
22
24
|
3. Spawn `session-handoff` in persist mode ONLY if step 2 failed (Amp: isolated `subagent-session-handoff`). Fallback, never routine.
|
|
23
25
|
4. Memory MCP is an optional mirror: if tools are available, update `Change:<name>`, `Handoff:<name>`, `Decision:*` in one call; unavailability never blocks closing.
|
|
24
26
|
5. Paste CLI stdout as one fenced block. First line `/opsx:…`. Body uses `project.agent_language`. Self-contained (Done/Decisions/Blocked/spawn/HARD STOP). No banner.
|
|
25
|
-
6.
|
|
27
|
+
6. If runtime is cloud: after persist, `git add openspec/changes/<name>/` → `git commit` → `git push` → `npx agent-orchestrator-kit handoff <name> --cloud-check` (exit 0 required). Closing without this is an incomplete handoff. Persist prints these steps on stderr; the CLI never runs `git commit` / `git push`.
|
|
28
|
+
7. Stop. Next role = new chat.
|
|
26
29
|
|
|
27
30
|
## Archive exception
|
|
28
31
|
`npx agent-orchestrator-kit archive <name>` writes the final `handoff.md` (`next_command: none`) in the archive folder and upserts memory itself. After a successful archive no fenced next-prompt is required — the pipeline is complete.
|
|
@@ -133,7 +133,7 @@ Archive is one deterministic CLI call — `npx agent-orchestrator-kit archive <n
|
|
|
133
133
|
**Start of each session:**
|
|
134
134
|
1. Honor the pasted `/opsx:<phase> <name>` command and announce that role.
|
|
135
135
|
2. Run `npx agent-orchestrator-kit status` (or `npx openspec list --json`) and read `orchestrator.yaml`; resolve the active change and gates.
|
|
136
|
-
3. Run `npx agent-orchestrator-kit handoff --restore` (or `handoff <name> --restore`).
|
|
136
|
+
3. Run `npx agent-orchestrator-kit handoff --restore` (or `handoff <name> --restore`). Accumulated decisions print from git-tracked `openspec/changes/<name>/decisions.md`, not from Memory.
|
|
137
137
|
4. Read Memory entities `Change:<name>`, `Handoff:<name>`, and `Decision:*` when MCP works.
|
|
138
138
|
5. If restore CLI fails and Memory is empty, read `openspec/changes/<name>/handoff.md`; Memory failure alone is not a blocker.
|
|
139
139
|
6. Spawn `session-handoff` in restore mode **only if** `handoff --restore` failed or printed no briefing (Amp: isolated `subagent-session-handoff`). Skip this spawn when CLI restore exits 0.
|
|
@@ -146,7 +146,7 @@ Archive is one deterministic CLI call — `npx agent-orchestrator-kit archive <n
|
|
|
146
146
|
|
|
147
147
|
**End of each session (HARD STOP — you are NOT done):**
|
|
148
148
|
1. Write `openspec/changes/<name>/handoff.md` in the parent using the template below.
|
|
149
|
-
2. Run `npx agent-orchestrator-kit handoff <name>` and require exit 0. The CLI upserts Memory JSON with an absolute path and prints the expanded self-contained prompt on stdout. Spawn `session-handoff` in persist mode ONLY if this CLI step failed.
|
|
149
|
+
2. Run `npx agent-orchestrator-kit handoff <name>` and require exit 0. The CLI appends non-empty Decisions into append-only `openspec/changes/<name>/decisions.md` (the git canon), upserts Memory JSON with an absolute path (`Decision:*` is a file→Memory mirror only), and prints the expanded self-contained prompt on stdout. Spawn `session-handoff` in persist mode ONLY if this CLI step failed.
|
|
150
150
|
3. If Memory MCP tools are available, mirror `Change:<name>`, `Handoff:<name>`, and new `Decision:<topic>` entities in one call — optional; its absence never blocks closing.
|
|
151
151
|
4. Paste the CLI stdout as one fenced next-session prompt. First line is `/opsx:<next> <name>`; body uses `project.agent_language`; keep Done/Decisions/Blocked/spawn/HARD STOP complete. No banner. Do not emit a thin “read Memory” stub.
|
|
152
152
|
5. Do not start the next phase in this chat. If apply, include build/lint status in the persisted Done section.
|
|
@@ -193,6 +193,10 @@ Archive is one deterministic CLI call — `npx agent-orchestrator-kit archive <n
|
|
|
193
193
|
- do not mix phases
|
|
194
194
|
- conductor must spawn specialists
|
|
195
195
|
|
|
196
|
+
## Runtime
|
|
197
|
+
- runtime: <local | cloud>
|
|
198
|
+
- agent_id: <id | none>
|
|
199
|
+
|
|
196
200
|
## Prompt
|
|
197
201
|
|
|
198
202
|
The Prompt section is overwritten by `npx agent-orchestrator-kit handoff <name>`. Do not hand-write a thin stub.
|
|
@@ -214,7 +218,7 @@ The Prompt section is overwritten by `npx agent-orchestrator-kit handoff <name>`
|
|
|
214
218
|
|
|
215
219
|
Before specialist work, the parent MUST restore context in order: honor the pasted `/opsx:*` command; run `npx agent-orchestrator-kit handoff --restore` (the CLI briefing is canonical — no separate Memory MCP read step); if the CLI failed, read `openspec/changes/<name>/handoff.md`; spawn `session-handoff` in restore mode ONLY when both failed. Missing Memory MCP never blocks a session. With one active change, free-form “continue” uses `Handoff.next_command` instead of asking for the phase. Amp spawns any needed subagent as an isolated `subagent-*` skill.
|
|
216
220
|
|
|
217
|
-
Before declaring a session closed, the parent MUST, in order: (1) write `openspec/changes/<name>/handoff.md` itself, (2) run `npx agent-orchestrator-kit handoff <name>` (exit 0) — spawn `session-handoff` persist ONLY if this CLI step failed, (3) paste the CLI stdout prompt whose first line is `/opsx:<next> <name>`. Memory MCP mirroring is an optional single call. The prompt has no `NEXT_SESSION_PROMPT` label, uses `project.agent_language`, and MUST be self-contained (Done, Decisions, Blocked, attach, spawn, HARD STOP) so the next thread can run if Memory MCP is ignored. Never start the next phase in the current chat.
|
|
221
|
+
Before declaring a session closed, the parent MUST, in order: (1) write `openspec/changes/<name>/handoff.md` itself, (2) run `npx agent-orchestrator-kit handoff <name>` (exit 0) — this CLI appends `decisions.md` and mirrors `Decision:*` file→Memory; spawn `session-handoff` persist ONLY if this CLI step failed, (3) paste the CLI stdout prompt whose first line is `/opsx:<next> <name>`. Memory MCP mirroring is an optional single call. Never write Memory back into `decisions.md`. The prompt has no `NEXT_SESSION_PROMPT` label, uses `project.agent_language`, and MUST be self-contained (Done, Decisions, Blocked, attach, spawn, HARD STOP) so the next thread can run if Memory MCP is ignored. Never start the next phase in the current chat. Write session artifacts only to git-tracked paths (never `/tmp`, never gitignored caches). If runtime is cloud: after persist, commit → push → `npx agent-orchestrator-kit handoff <name> --cloud-check` with exit 0; closing without that is an incomplete handoff.
|
|
218
222
|
|
|
219
223
|
| Entity | Required fields |
|
|
220
224
|
|--------|-----------------|
|
|
@@ -12,8 +12,8 @@ When spawned, Amp runs this skill as an isolated subagent (`subagent-session-han
|
|
|
12
12
|
Use when the parent's restore failed (CLI restore and handoff.md both unavailable).
|
|
13
13
|
|
|
14
14
|
1. Run `npx agent-orchestrator-kit status`.
|
|
15
|
-
2. Run `npx agent-orchestrator-kit handoff --restore` (add `<name>` when known).
|
|
16
|
-
3. If Memory MCP tools are available, read `Change:<name>`, `Handoff:<name>`, and `Decision
|
|
15
|
+
2. Run `npx agent-orchestrator-kit handoff --restore` (add `<name>` when known). The briefing prints accumulated decisions from git-tracked `openspec/changes/<name>/decisions.md` (canon), not from Memory.
|
|
16
|
+
3. If Memory MCP tools are available, read `Change:<name>`, `Handoff:<name>`, and `Decision:*` (the latter is a file→Memory mirror of `decisions.md`).
|
|
17
17
|
4. If CLI restore fails, read `openspec/changes/<name>/handoff.md` when it exists.
|
|
18
18
|
5. Return the restore report. Do not spawn the phase specialist yourself.
|
|
19
19
|
|
|
@@ -21,13 +21,15 @@ Use when the parent's restore failed (CLI restore and handoff.md both unavailabl
|
|
|
21
21
|
|
|
22
22
|
Use when the parent's persist failed (`npx agent-orchestrator-kit handoff <name>` did not exit 0). A session is not closed until persist succeeds.
|
|
23
23
|
|
|
24
|
-
1. Write or update `openspec/changes/<name>/handoff.md` with every required section: Closed role, Change, Done, Decisions, Blocked, Next command, Next role, Attach, Subagents to spawn, Constraints.
|
|
25
|
-
2. Run `npx agent-orchestrator-kit handoff <name>` and require exit 0. This upserts `.cursor/memory.json` using an absolute path and prints the expanded next-session prompt on stdout.
|
|
26
|
-
3. If Memory MCP tools are available, also create/update `Change:<name>`, `Handoff:<name>`, and each `Decision:<topic>` to match
|
|
24
|
+
1. Write or update `openspec/changes/<name>/handoff.md` with every required section: Closed role, Change, Done, Decisions, Blocked, Next command, Next role, Attach, Subagents to spawn, Constraints, Runtime.
|
|
25
|
+
2. Run `npx agent-orchestrator-kit handoff <name>` and require exit 0. This appends non-empty Decisions into append-only `openspec/changes/<name>/decisions.md` (git canon), upserts `.cursor/memory.json` using an absolute path (`Decision:*` mirrors that file, never the reverse), and prints the expanded next-session prompt on stdout. Cloud sessions pass `--runtime cloud` (or `AOK_RUNTIME` / `AOK_AGENT_ID`).
|
|
26
|
+
3. If Memory MCP tools are available, also create/update `Change:<name>`, `Handoff:<name>`, and each `Decision:<topic>` to match `decisions.md`. MCP failure is not a blocker after the CLI succeeds.
|
|
27
27
|
4. Put the CLI stdout prompt (first line `/opsx:…`) into **Next prompt** unchanged. Do not shorten it. Do not add a banner.
|
|
28
|
+
5. If runtime is cloud: after persist, commit and push `openspec/changes/<name>/`, then `npx agent-orchestrator-kit handoff <name> --cloud-check` (exit 0 required). Closing without this is an incomplete handoff. The CLI never runs `git commit` / `git push`.
|
|
28
29
|
|
|
29
30
|
## Rules
|
|
30
31
|
|
|
32
|
+
- Write session artifacts only to git-tracked paths (never `/tmp`, never gitignored caches).
|
|
31
33
|
- Do NOT edit `src/`, tests, main specs, `tasks.md` checkboxes, or phase artifacts (`proposal.md`, `review.md`, `design-brief.md`) except `handoff.md`.
|
|
32
34
|
- Do NOT start the next OpenSpec phase.
|
|
33
35
|
- Do NOT return a thin prompt. The next thread must be able to run if Memory MCP is ignored.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{"type":"entity","name":"Change:add-factory-memory-and-skills","entityType":"Change","observations":["status: archived","tasks: 9/9","last_role: Archiver","review: APPROVE","summary: archived to openspec/changes/archive/2026-08-27-add-factory-memory-and-skills"]}
|
|
2
|
+
{"type":"entity","name":"Handoff:add-factory-memory-and-skills","entityType":"Handoff","observations":["next_role: none","next_command: none","summary: archived to openspec/changes/archive/2026-08-27-add-factory-memory-and-skills","blocked: none"]}
|
|
3
|
+
{"type":"entity","name":"Decision:apply-complete","entityType":"Decision","observations":["all 9 tasks implemented and verified (npm test 101/101, openspec validate --strict, gate-check --tasks)","change: add-factory-memory-and-skills","date: 2026-08-27"]}
|
|
4
|
+
{"type":"entity","name":"Decision:m1-followed","entityType":"Decision","observations":["task 2.3 Skill health stale/missing verified in a temporary init+sync project (smoke test), not in the kit repo","change: add-factory-memory-and-skills","date: 2026-08-27"]}
|
|
5
|
+
{"type":"entity","name":"Decision:m2-followed","entityType":"Decision","observations":["skills.kit drift test iterates all five orchestrator.yaml files against templates/.agents/skills/","change: add-factory-memory-and-skills","date: 2026-08-27"]}
|
|
6
|
+
{"type":"entity","name":"Decision:i1-honored","entityType":"Decision","observations":["did not change templates/orchestrator.yaml handoff.spawn_handoff_subagent (still false)","change: add-factory-memory-and-skills","date: 2026-08-27"]}
|
|
7
|
+
{"type":"relation","from":"Change:add-factory-memory-and-skills","to":"Handoff:add-factory-memory-and-skills","relationType":"hasHandoff"}
|
|
8
|
+
{"type":"relation","from":"Change:add-factory-memory-and-skills","to":"Decision:apply-complete","relationType":"hasDecision"}
|
|
9
|
+
{"type":"relation","from":"Change:add-factory-memory-and-skills","to":"Decision:m1-followed","relationType":"hasDecision"}
|
|
10
|
+
{"type":"relation","from":"Change:add-factory-memory-and-skills","to":"Decision:m2-followed","relationType":"hasDecision"}
|
|
11
|
+
{"type":"relation","from":"Change:add-factory-memory-and-skills","to":"Decision:i1-honored","relationType":"hasDecision"}
|
|
@@ -64,8 +64,22 @@ mcp:
|
|
|
64
64
|
optional:
|
|
65
65
|
- figma
|
|
66
66
|
- github
|
|
67
|
+
- gitlab
|
|
67
68
|
- browser
|
|
68
69
|
|
|
70
|
+
skills:
|
|
71
|
+
kit:
|
|
72
|
+
- agent-orchestration
|
|
73
|
+
- openspec-howto
|
|
74
|
+
- openspec-explore
|
|
75
|
+
- openspec-propose
|
|
76
|
+
- openspec-apply-change
|
|
77
|
+
- openspec-archive-change
|
|
78
|
+
- openspec-sync-specs
|
|
79
|
+
- spec-workflow-openspec
|
|
80
|
+
stack: []
|
|
81
|
+
external: ""
|
|
82
|
+
|
|
69
83
|
figma:
|
|
70
84
|
env_file: .agents/figma.local.env
|
|
71
85
|
token_key: FIGMA_ACCESS_TOKEN
|
|
@@ -83,6 +97,8 @@ cli:
|
|
|
83
97
|
handoff: npx agent-orchestrator-kit handoff <name>
|
|
84
98
|
handoff_restore: npx agent-orchestrator-kit handoff --restore
|
|
85
99
|
memory_setup: npx agent-orchestrator-kit memory-setup
|
|
100
|
+
mcp_setup: npx agent-orchestrator-kit mcp-setup
|
|
101
|
+
hooks_setup: npx agent-orchestrator-kit hooks-setup
|
|
86
102
|
openspec_list: npx openspec list
|
|
87
103
|
openspec_validate_change: npx openspec validate <name> --strict --type change
|
|
88
104
|
openspec_validate_all: npx openspec validate --all --strict
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const { spawn } = require('child_process');
|
|
3
|
+
|
|
4
|
+
const child = spawn('npx', ['-y', '@playwright/mcp'], {
|
|
5
|
+
stdio: 'inherit',
|
|
6
|
+
env: process.env,
|
|
7
|
+
shell: process.platform === 'win32',
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
child.on('exit', (code, signal) => {
|
|
11
|
+
if (signal) {
|
|
12
|
+
process.kill(process.pid, signal);
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
process.exit(code == null ? 1 : code);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
child.on('error', (error) => {
|
|
19
|
+
console.error(`[browser-mcp-launcher] Failed to start Playwright MCP: ${error.message}`);
|
|
20
|
+
process.exit(1);
|
|
21
|
+
});
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const { spawn } = require('child_process');
|
|
3
|
+
const { existsSync, readFileSync } = require('fs');
|
|
4
|
+
const { join } = require('path');
|
|
5
|
+
|
|
6
|
+
const projectDir = join(__dirname, '..');
|
|
7
|
+
const envPath = join(projectDir, '.agents', 'github.local.env');
|
|
8
|
+
|
|
9
|
+
function readLocalEnv() {
|
|
10
|
+
if (!existsSync(envPath)) {
|
|
11
|
+
console.error(
|
|
12
|
+
`[github-mcp-launcher] Missing ${envPath}. Copy .agents/github.local.env.example → .agents/github.local.env and add GITHUB_PERSONAL_ACCESS_TOKEN (do not paste the token into chat).`
|
|
13
|
+
);
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const values = {};
|
|
18
|
+
for (const line of readFileSync(envPath, 'utf-8').split(/\r?\n/)) {
|
|
19
|
+
const trimmed = line.trim();
|
|
20
|
+
if (!trimmed || trimmed.startsWith('#')) continue;
|
|
21
|
+
const eq = trimmed.indexOf('=');
|
|
22
|
+
if (eq === -1) continue;
|
|
23
|
+
const key = trimmed.slice(0, eq).trim();
|
|
24
|
+
let value = trimmed.slice(eq + 1).trim();
|
|
25
|
+
if (
|
|
26
|
+
(value.startsWith('"') && value.endsWith('"')) ||
|
|
27
|
+
(value.startsWith("'") && value.endsWith("'"))
|
|
28
|
+
) {
|
|
29
|
+
value = value.slice(1, -1);
|
|
30
|
+
}
|
|
31
|
+
values[key] = value;
|
|
32
|
+
}
|
|
33
|
+
return values;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const envValues = readLocalEnv();
|
|
37
|
+
const token = envValues.GITHUB_PERSONAL_ACCESS_TOKEN || envValues.GITHUB_TOKEN || '';
|
|
38
|
+
if (!token) {
|
|
39
|
+
console.error(
|
|
40
|
+
'[github-mcp-launcher] GITHUB_PERSONAL_ACCESS_TOKEN is empty in .agents/github.local.env. Add a GitHub personal access token locally (never in chat).'
|
|
41
|
+
);
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const child = spawn('npx', ['-y', '@modelcontextprotocol/server-github'], {
|
|
46
|
+
stdio: 'inherit',
|
|
47
|
+
env: {
|
|
48
|
+
...process.env,
|
|
49
|
+
GITHUB_PERSONAL_ACCESS_TOKEN: token,
|
|
50
|
+
GITHUB_TOKEN: token,
|
|
51
|
+
},
|
|
52
|
+
shell: process.platform === 'win32',
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
child.on('exit', (code, signal) => {
|
|
56
|
+
if (signal) {
|
|
57
|
+
process.kill(process.pid, signal);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
process.exit(code == null ? 1 : code);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
child.on('error', (error) => {
|
|
64
|
+
console.error(`[github-mcp-launcher] Failed to start GitHub MCP: ${error.message}`);
|
|
65
|
+
process.exit(1);
|
|
66
|
+
});
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const { spawn } = require('child_process');
|
|
3
|
+
const { existsSync, readFileSync } = require('fs');
|
|
4
|
+
const { join } = require('path');
|
|
5
|
+
|
|
6
|
+
const projectDir = join(__dirname, '..');
|
|
7
|
+
const envPath = join(projectDir, '.agents', 'gitlab.local.env');
|
|
8
|
+
const DEFAULT_API_URL = 'https://gitlab.com/api/v4';
|
|
9
|
+
|
|
10
|
+
function readLocalEnv() {
|
|
11
|
+
if (!existsSync(envPath)) {
|
|
12
|
+
console.error(
|
|
13
|
+
`[gitlab-mcp-launcher] Missing ${envPath}. Copy .agents/gitlab.local.env.example → .agents/gitlab.local.env and add GITLAB_PERSONAL_ACCESS_TOKEN (do not paste the token into chat).`
|
|
14
|
+
);
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const values = {};
|
|
19
|
+
for (const line of readFileSync(envPath, 'utf-8').split(/\r?\n/)) {
|
|
20
|
+
const trimmed = line.trim();
|
|
21
|
+
if (!trimmed || trimmed.startsWith('#')) continue;
|
|
22
|
+
const eq = trimmed.indexOf('=');
|
|
23
|
+
if (eq === -1) continue;
|
|
24
|
+
const key = trimmed.slice(0, eq).trim();
|
|
25
|
+
let value = trimmed.slice(eq + 1).trim();
|
|
26
|
+
if (
|
|
27
|
+
(value.startsWith('"') && value.endsWith('"')) ||
|
|
28
|
+
(value.startsWith("'") && value.endsWith("'"))
|
|
29
|
+
) {
|
|
30
|
+
value = value.slice(1, -1);
|
|
31
|
+
}
|
|
32
|
+
values[key] = value;
|
|
33
|
+
}
|
|
34
|
+
return values;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const envValues = readLocalEnv();
|
|
38
|
+
const token = envValues.GITLAB_PERSONAL_ACCESS_TOKEN || envValues.GITLAB_TOKEN || '';
|
|
39
|
+
if (!token) {
|
|
40
|
+
console.error(
|
|
41
|
+
'[gitlab-mcp-launcher] GITLAB_PERSONAL_ACCESS_TOKEN is empty in .agents/gitlab.local.env. Add a GitLab personal access token locally (never in chat).'
|
|
42
|
+
);
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const apiUrl = envValues.GITLAB_API_URL || DEFAULT_API_URL;
|
|
47
|
+
|
|
48
|
+
const child = spawn('npx', ['-y', '@modelcontextprotocol/server-gitlab'], {
|
|
49
|
+
stdio: 'inherit',
|
|
50
|
+
env: {
|
|
51
|
+
...process.env,
|
|
52
|
+
GITLAB_PERSONAL_ACCESS_TOKEN: token,
|
|
53
|
+
GITLAB_TOKEN: token,
|
|
54
|
+
GITLAB_API_URL: apiUrl,
|
|
55
|
+
},
|
|
56
|
+
shell: process.platform === 'win32',
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
child.on('exit', (code, signal) => {
|
|
60
|
+
if (signal) {
|
|
61
|
+
process.kill(process.pid, signal);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
process.exit(code == null ? 1 : code);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
child.on('error', (error) => {
|
|
68
|
+
console.error(`[gitlab-mcp-launcher] Failed to start GitLab MCP: ${error.message}`);
|
|
69
|
+
process.exit(1);
|
|
70
|
+
});
|