archgen-skill 0.0.1

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.
@@ -0,0 +1,105 @@
1
+ # Artifact templates — copy, fill, never invent structure
2
+
3
+ ## architecture.yaml (LARGE scope)
4
+
5
+ ```yaml
6
+ name: Acme Shop
7
+ slug: acme-shop # becomes .archgen/acme-shop/
8
+ stack:
9
+ language: typescript
10
+ runtime: node20
11
+ framework: nextjs
12
+ database: postgres
13
+ structure: # planned folder tree — planned BEFORE code exists
14
+ - path: src/features/<feature>/
15
+ purpose: feature modules (api, internal, tests colocated)
16
+ - path: src/shared/
17
+ purpose: cross-feature utilities, no feature imports
18
+ - path: src/config/
19
+ purpose: env parsing + constants
20
+ modules:
21
+ - name: catalog
22
+ responsibility: product browsing + search
23
+ owns: ["src/features/catalog/**"]
24
+ - name: checkout
25
+ responsibility: cart → payment orchestration
26
+ owns: ["src/features/checkout/**"]
27
+ decisions: # ADR-lite; full ADRs live in decisions/
28
+ - id: D1
29
+ title: Postgres over MongoDB
30
+ context: transactional orders + reporting queries
31
+ decision: Postgres 16 with Prisma
32
+ consequences: schema migrations required per release
33
+ ```
34
+
35
+ ## tasks.yaml (canonical shape)
36
+
37
+ ```yaml
38
+ # comment lines are preserved by set-status.mjs — annotate freely
39
+ tasks:
40
+ # Core pipeline — do first
41
+ - id: C
42
+ title: Scaffold project skeleton + config loading
43
+ depends_on: []
44
+ file_ownership: ["src/config/**", "package.json"]
45
+ acceptance:
46
+ - "npm run build exits 0"
47
+ - "config loads from env with typed schema"
48
+ - id: B
49
+ title: Catalog API endpoints
50
+ depends_on: [C]
51
+ file_ownership: ["src/features/catalog/**"]
52
+ acceptance:
53
+ - "GET /products returns seeded list"
54
+ - id: A
55
+ title: Checkout flow wired to catalog
56
+ depends_on: [B]
57
+ parallel_group: wave-final
58
+ file_ownership: ["src/features/checkout/**"]
59
+ artifacts: ["docs/checkout-flow.md"]
60
+ acceptance:
61
+ - "e2e test completes purchase with stub payment"
62
+ ```
63
+
64
+ Rules encoded above: depends_on = prerequisites; ownership globs disjoint
65
+ within a wave; acceptance = objectively checkable statements.
66
+
67
+ ## SMALL-scope plan note (plans/<feature>.md)
68
+
69
+ ```markdown
70
+ # <feature> — plan note (SMALL)
71
+ Intent: <one paragraph>
72
+ Tasks: see tasks.yaml entries <ids>
73
+ Risks: <bullets or none>
74
+ ```
75
+
76
+ ## ADR template (decisions/NNNN-title.md)
77
+
78
+ ```markdown
79
+ # NNNN. <decision title>
80
+ Date: YYYY-MM-DD · Status: accepted
81
+ ## Context
82
+ <forces at play>
83
+ ## Decision
84
+ <what we chose>
85
+ ## Consequences
86
+ <positive / negative / neutral>
87
+ ```
88
+
89
+ ## Mermaid snippets
90
+
91
+ C4 context:
92
+ ```mermaid
93
+ graph TB
94
+ user([Customer]) --> sys[Acme Shop]
95
+ sys --> pay[Stripe]
96
+ sys --> mail[Email Service]
97
+ ```
98
+
99
+ Container:
100
+ ```mermaid
101
+ graph LR
102
+ web[Next.js App] --> api[API Routes]
103
+ api --> db[(Postgres)]
104
+ api --> cache[(Redis)]
105
+ ```
@@ -0,0 +1,70 @@
1
+ # Code standards — contractual, verifier-enforced
2
+
3
+ Workers and planners follow these. The verifier rejects tasks whose plan or
4
+ output violates them. Every rule exists because its absence produced real
5
+ production incidents somewhere.
6
+
7
+ ## Typing (TypeScript projects)
8
+
9
+ - NO ANY: `any` is BANNED — including implicit anys and `as any` casts. Enable `"strict": true` plus
10
+ `noImplicitAny`, `strictNullChecks`, `noUncheckedIndexedAccess`.
11
+ - No unhandled `undefined`/null: validate at boundaries (env parsing, API
12
+ input) with a schema; inside the codebase use non-optional types + explicit
13
+ result objects for fallible operations.
14
+ - Prefer discriminated unions over boolean-flag parameters.
15
+ - Generated Python/Rust/Go equivalents: type hints mandatory / no `unwrap()` on
16
+ fallibles / handle errors explicitly — same discipline per language.
17
+
18
+ ## File & module limits
19
+
20
+ - HARD CEILING: files < 1000 LOC. Split well before — when a file gains a
21
+ second responsibility, that IS the split signal.
22
+ - One public purpose per module. If the docstring needs "and", split.
23
+
24
+ ## Folder structure (planned in architecture.yaml BEFORE coding)
25
+
26
+ ```
27
+ src/
28
+ features/<name>/ # feature-first: everything a feature owns
29
+ api/ # inbound contracts (routes/handlers)
30
+ internal/ # private implementation
31
+ tests/ # colocated tests mirror structure
32
+ shared/ # cross-feature ONLY; may not import features/
33
+ config/ # typed env + constants
34
+ ```
35
+
36
+ - Feature modules may import `shared/`; `shared/` imports NOTHING from features.
37
+ - Tests live beside code (mirrored path), never a distant `/tests` desert.
38
+
39
+ ## File naming
40
+
41
+ Per-language conventions (professional, descriptive, consistent):
42
+
43
+ | Language | Source files | Components/classes | Tests |
44
+ |---|---|---|---|
45
+ | TypeScript | `kebab-case.ts` | `PascalCase.tsx` components, `PascalCase` classes | `<subject>.test.ts` colocated |
46
+ | Python | `snake_case.py` modules | `PascalCase` classes, `snake_case` functions | `test_<subject>.py` mirrored |
47
+ | Rust | `snake_case.rs` modules | `PascalCase` types/traits | `#[cfg(test)] mod tests` inline or `tests/` |
48
+ | Go | `snake_case.go` packages | `PascalCase` exported / `camelCase` internal | `<subject>_test.go` same dir |
49
+
50
+ - Descriptive > clever: `rate-limiter.ts` not `rl.ts`; `parse-config.ts` not
51
+ `utils2.ts`.
52
+ - BANNED names: `utils.ts`, `misc.ts`, `helpers.ts`, `temp*`, `final*`,
53
+ `copy*`, numbered duplicates (`auth2.ts`) — split by responsibility instead.
54
+
55
+ ## Comments
56
+
57
+ - WHY at decision points: tradeoffs taken, non-obvious constraints, links to
58
+ decisions ("see ADR D3").
59
+ - Public APIs get doc comments: purpose, params, failure modes.
60
+ - NO noise: no `// increment i`, no commented-out code, no change-log comments
61
+ (git remembers).
62
+
63
+ ## Enforcement hooks
64
+
65
+ - tasks.yaml acceptance criteria MUST include at least one objectively
66
+ checkable statement (command exit, observable output).
67
+ - The verifier runs verify-plan.mjs AND reads plans against this file;
68
+ violations = ISSUES, not warnings.
69
+ - Workers receive this reference in their prompt contract; "I didn't know" is
70
+ not available to them.
@@ -0,0 +1,66 @@
1
+ # Interview playbook — requirement elicitation
2
+
3
+ Goal: complete, conflict-free requirements in the FEWEST round-trips.
4
+ Batch 3–5 questions per message. Never ask what you can infer.
5
+
6
+ ## Round 1 — business frame (ask the user)
7
+
8
+ 1. What problem does this solve, and for whom? (one sentence is enough)
9
+ 2. What does success look like — measurable if possible?
10
+ 3. Hard constraints: deadline, budget, must-keep systems?
11
+
12
+ ## Round 2 — technical frame (infer first, confirm second)
13
+
14
+ Draft answers from context (existing repo, stated stack), then confirm:
15
+ 4. Stack + hosting target correct? (state your inference)
16
+ 5. Scale expectation: users/reqs/day, data growth?
17
+ 6. Integration surfaces: auth, payments, email, existing APIs?
18
+
19
+ ## Round 3 — constraints & risks
20
+
21
+ 7. Compliance needs? (GDPR/HIPAA/PCI — checklist level only)
22
+ 8. What must NOT change?
23
+ 9. Top 2 risks the user already knows about?
24
+
25
+ ## Conflict detection
26
+
27
+ While collecting, watch for and surface immediately:
28
+ - Scale vs budget contradictions ("1M users" + "cheapest VPS")
29
+ - Feature vs constraint collisions ("real-time" + "no websockets allowed")
30
+ - Requirement vs existing-architecture conflicts (brownfield: check codebase-map)
31
+
32
+ Format: "I see a tension between X and Y. Which wins?" — one per message,
33
+ resolve before proceeding. [wait for user]
34
+
35
+ ## Answers-file format (machine-readable, enables non-interactive runs)
36
+
37
+ For scripted E2E or re-runs, requirements may come from a file instead of
38
+ conversation — `.archgen/<slug>/answers.yaml`:
39
+
40
+ ```yaml
41
+ scope_class: MEDIUM # SMALL | MEDIUM | LARGE
42
+ problem: one-line problem statement
43
+ success_criteria:
44
+ - measurable outcome
45
+ constraints:
46
+ - must-not-change items
47
+ stack:
48
+ language: typescript
49
+ runtime: node
50
+ hosting: vercel
51
+ integrations: [auth0, stripe]
52
+ compliance: [] # checklist placeholders only
53
+ risks:
54
+ - known risk text
55
+ ```
56
+
57
+ The orchestrator treats answers.yaml as authoritative user input and skips
58
+ the conversational rounds when it exists and parses cleanly.
59
+
60
+ ## Completion test
61
+
62
+ Requirements are done when ALL hold:
63
+ - Every ROUND-1 question answered
64
+ - All drafted inferences confirmed or corrected
65
+ - Zero unresolved conflicts
66
+ - Scope class agreed (SMALL/MEDIUM/LARGE) — this gates artifact generation
@@ -0,0 +1,46 @@
1
+ # MCP installation and skill fetching
2
+
3
+ ## INSTALL-MCP procedure (approval-gated)
4
+
5
+ 1. **Identify** the platform (SKILL.md Step 0), load its row from
6
+ references/platforms.md section MCP: config file, top-level key, quirks.
7
+ 2. **Prefer the platform CLI** where the table lists one. It handles scope and
8
+ file selection correctly:
9
+ - `claude mcp add --scope project --transport http <name> <url>`
10
+ - `codex mcp add <name> --url <url>` or `codex mcp add <n> -- cmd args`
11
+ - `gemini mcp add -s project -t http <name> <url>`
12
+ 3. No CLI available: draft the exact config diff against the platform's real
13
+ shape (see assets/mcp-template.json for annotated canonical forms) and SHOW
14
+ it to the user. **USER APPROVAL GATE** — wait for an explicit yes before any
15
+ write; approval is never inferred from earlier steps.
16
+ 4. Apply, then apply the restart semantics from the platforms table.
17
+ 5. Verify the tool is visible after reload; report failure modes honestly.
18
+
19
+ Never write MCP configs silently. Never invent config shapes — the four known
20
+ top-level keys are mcpServers / servers / mcp / context_servers; remote URL
21
+ fields vary (url vs serverUrl vs httpUrl) per the platforms table.
22
+
23
+ ## FETCH-SKILL procedure
24
+
25
+ 1. Read assets/skill-registry.json. Match the current task domain against
26
+ entry `matches` patterns (e.g. frontend/UI work matches ui-skills).
27
+ 2. Install into the CURRENT platform's skill dir (platforms.md paths):
28
+ - Generic: `npx skills add <owner>/<repo>` (writes correct path for 75+
29
+ harnesses; `-g` for global).
30
+ - Entry-specific command when present (e.g. `npx ui-skills get baseline-ui`).
31
+ 3. Confirm files landed where expected; then FOLLOW the fetched skill's own
32
+ instructions for the task domain.
33
+ 4. Missing capability: web-search reputable skill repos, propose to user,
34
+ on approval append an entry to the registry (PR or local edit).
35
+
36
+ ## Registry entry shape
37
+
38
+ ```json
39
+ {
40
+ "name": "short-name",
41
+ "purpose": "when to reach for it",
42
+ "repo": "owner/repo",
43
+ "install": "npx skills add owner/repo",
44
+ "matches": ["frontend", "ui", "design"]
45
+ }
46
+ ```
@@ -0,0 +1,106 @@
1
+ # Orchestration playbook — survey, verify, dispatch
2
+
3
+ Sub-agent briefs and the wave-execution mechanics. The orchestrator (SKILL.md)
4
+ calls into these sections; workers never read this file.
5
+
6
+ ## §survey — brownfield codebase analysis brief
7
+
8
+ Dispatch 1–2 sub-agents with this prompt shape:
9
+
10
+ ```
11
+ TASK: Survey this repository to prepare a feature plan for: <feature request>
12
+ DELIVERABLE: write .archgen/<slug>/codebase-map.md containing EXACTLY these
13
+ sections:
14
+ ## Structure — top-2-levels folder tree w/ one-line purpose each
15
+ ## Modules — table: module | responsibility | key entry points
16
+ ## Conventions — naming, error-handling, test layout actually observed
17
+ ## Affected — files/modules the feature will touch, with evidence paths
18
+ SCOPE: read-only. Use codegraph MCP tools when available
19
+ (codegraph_explore / codegraph_files); otherwise Glob+Grep systematically.
20
+ VERIFY: every claim cites a real path; no guessed APIs.
21
+ ```
22
+
23
+ Accept the map only if every section is present and non-empty.
24
+
25
+ ## §verifier — plan review brief
26
+
27
+ Dispatch AFTER artifacts exist and validate.mjs passes. The verifier:
28
+
29
+ 1. Runs `node <skill>/scripts/verify-plan.mjs .archgen/<slug>/tasks.yaml --plan .archgen/<slug>/plans`
30
+ — deterministic floor: cycles, dangling refs, same-wave ownership overlap,
31
+ missing acceptance criteria, plan↔task coverage.
32
+ 2. Reads plans + tasks.yaml and judges what scripts cannot:
33
+ - Are wave boundaries sensible (no artificial serialization)?
34
+ - Do acceptance criteria objectively verify (command or observable)?
35
+ - Edge cases covered per SKILL.md right-sizing class?
36
+ - Code-standards compliance plausible for the planned structure?
37
+ 3. Returns EXACTLY one line verdict: `APPROVE` or `ISSUES:` + numbered list.
38
+
39
+ Orchestrator fixes issues (edits artifacts) and re-dispatches. Loop until
40
+ APPROVE — never present to the user before verifier approval.
41
+
42
+ ## §dispatch — wave execution
43
+
44
+ ### Tier 1: native sub-agents (preferred where strong)
45
+
46
+ - Claude Code: background Agent tool per task; add worktree isolation for
47
+ tasks whose ownership might brush shared files.
48
+ - Cursor: background subagents; request isolation when >2 parallel workers.
49
+ - Antigravity: invoke_subagent async.
50
+ - Codex: spawn_agent works but children can't nest — flatten the plan instead.
51
+ - Gemini CLI: parallel @agents are hub-and-spoke only AND have no isolation →
52
+ use them ONLY for read-only/research waves unless wrapping in worktrees.
53
+
54
+ ### Tier 2: bash fallback workers (universal floor)
55
+
56
+ ```bash
57
+ #!/usr/bin/env bash
58
+ set -uo pipefail
59
+ SLUG="<slug>"; ROOT="$(pwd)"; SKILL="<abs-path-to-skills/archgen>"
60
+ run_task() { # $1=id $2=prompt-file
61
+ local id="$1" pf="$2" log=".archgen/$SLUG/results/$id.log"
62
+ mkdir -p "$(dirname "$log")"
63
+ local body; body="$(cat "$pf")
64
+
65
+ You own exactly the file_ownership globs listed for this task in tasks.yaml. Follow archgen code-standards. On success run: node \"$SKILL/scripts/set-status.mjs\" .archgen/$SLUG/tasks.yaml \"$id\" done ; on failure set-status failed."
66
+ case "$ARCHGEN_HARNESS" in
67
+ claude) claude -p "$body" --output-format json --permission-mode acceptEdits > "$log" 2>&1 ;;
68
+ opencode) opencode run "$body" --auto --format json > "$log" 2>&1 ;;
69
+ codex) codex exec --sandbox workspace-write --json -o "$log.final" "$body" > "$log" 2>&1 ;;
70
+ gemini) gemini --output-format json "$body" > "$log" 2>&1 ;;
71
+ agy) agy -p --output-format json --print-timeout 15m "$body" > "$log" 2>&1 ;;
72
+ *) echo "unknown harness: $ARCHGEN_HARNESS" >&2; return 9 ;;
73
+ esac
74
+
75
+ You own exactly: $(node "$SKILL/scripts/impact.mjs" .archgen/$SLUG/tasks.yaml "$id" >/dev/null 2>&1 && echo 'see tasks.yaml file_ownership'). Follow archgen code-standards. On success run: node "$SKILL/scripts/set-status.mjs" .archgen/$SLUG/tasks.yaml "$id" done ; on failure set-status failed." \
76
+ }
77
+ # Wave N: launch all frontier tasks in parallel…
78
+ for t in $(node "$SKILL/scripts/next-tasks.mjs" .archgen/$SLUG/tasks.yaml \
79
+ | node -e 'let d="";process.stdin.on("data",c=>d+=c).on("end",()=>console.log(JSON.parse(d).waves[0].map(t=>t.id).join(" ")))'); do
80
+ run_task "$t" ".archgen/$SLUG/results/$t.prompt" & pids="$pids $!"
81
+ done
82
+ fail=0; for p in $pids; do wait "$p" || fail=1; done
83
+ exit $fail # orchestrator inspects statuses before next wave
84
+ ```
85
+
86
+ Isolation upgrade for Tier 2 when ownership borders are tight:
87
+
88
+ ```bash
89
+ git worktree add ".worktrees/$id" -b "task-$id"
90
+ # run worker with cwd=.worktrees/$id, then merge task-$id on success
91
+ ```
92
+
93
+ ### Worker prompt contract (both tiers)
94
+
95
+ Every worker receives: task id+title, its acceptance criteria verbatim, its
96
+ file_ownership globs ("edit NOTHING outside these"), the code-standards
97
+ reference, and the done/failed status-update command. Workers do NOT talk to
98
+ each other; coordination happens only through tasks.yaml state.
99
+
100
+ ## Failure policy
101
+
102
+ - Worker exit ≠ 0 OR status=failed → leave it failed. NEVER auto-retry.
103
+ - Downstream tasks stay blocked by the resolver (blockedByFailure).
104
+ - Report to user: failed id, log path, proposed fix-task description.
105
+ [wait for user] A fix task gets fresh id, depends_on=[], ownership of the
106
+ failed task's globs.
@@ -0,0 +1,79 @@
1
+ # Platform capability matrix (August 2026)
2
+
3
+ Facts verified against official vendor docs; cells marked UNVERIFIED could not be
4
+ confirmed. The orchestrator loads ONLY the row matching Step-0 detection.
5
+
6
+ ## Skill install paths
7
+
8
+ | Platform | Project path | Global path | Notes |
9
+ |---|---|---|---|
10
+ | Claude Code | `.claude/skills/<name>/` | `~/.claude/skills/<name>/` | Plugin marketplace: `/plugin install x@mkt`; skills hot-reload |
11
+ | OpenCode | `.opencode/skills/` (+ reads `.claude/`, `.agents/`) | `~/.config/opencode/skills/` (+ `~/.claude/`, `~/.agents/`) | Walks up to git root |
12
+ | Cursor | `.agents/skills/`, `.cursor/skills/` | `~/.agents/skills/`, `~/.cursor/skills/` | ≥2.4 native; also scans `.claude/`, `.codex/`; nesting OK |
13
+ | Windsurf | `.windsurf/skills/` | `~/.codeium/windsurf/skills/` | Enterprise system paths also read |
14
+ | VS Code + Copilot | `.github/skills/` (+ `.claude/`, `.agents/`) | `~/.copilot/skills/` (+ `~/.claude/`, `~/.agents/`) | Extra dirs via chat.agentSkillsLocations |
15
+ | Codex CLI | `.agents/skills/` (crawls up to repo root) | `~/.agents/skills/` (legacy `~/.codex/skills/`) | `$skill-installer` built in |
16
+ | Gemini CLI | `.gemini/skills/` or `.agents/skills/` | `~/.gemini/skills/` or `~/.agents/skills/` | `gemini skills install <git-url> --consent` |
17
+ | Antigravity | `<ws>/.agents/skills/` | `~/.gemini/config/skills/` | Backward-supports `.agent/skills`; name frontmatter OPTIONAL here |
18
+ | Zed | `<project>/.agents/skills/` ONLY | `~/.agents/skills/` ONLY | FLAT layout — no nesting; worktree-trust gate on project skills |
19
+ | Kiro | `.kiro/skills/` | `~/.kiro/skills/` | Custom agents need explicit `resources: ["skill://.kiro/skills/**/SKILL.md"]` |
20
+ | Trae | `.trae/skills/` (opt-in `.agents/`) | `~/.trae/skills/` | `.trae` wins collisions; CN variant separate |
21
+ | Claude Desktop | — (account-scoped) | GUI ZIP upload only | Scripts run sandboxed, NOT local shell |
22
+
23
+ Universal fallback: `.agents/skills/` project + `~/.agents/skills/` user works
24
+ across most harnesses. Primary distribution: `npx skills add <repo>` (75+ agents).
25
+
26
+ ## MCP configuration
27
+
28
+ Four different top-level keys exist — NEVER assume `mcpServers`:
29
+
30
+ | Platform | File(s) | Key | stdio fields | Remote URL field | CLI add? |
31
+ |---|---|---|---|---|---|
32
+ | Claude Code | `.mcp.json` (project) / `~/.claude.json` (local/user) | `mcpServers` | command,args[,env] type:"stdio" | `url`+headers type:"http"/"sse" | `claude mcp add --scope project\|local\|user --transport stdio\|http\|sse` |
33
+ | Claude Desktop | `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) / `%APPDATA%\Claude\` (Win) / `~/.config/Claude/` (Linux) | `mcpServers` | command,args,env | UI Connectors preferred; file `url` UNVERIFIED | none |
34
+ | OpenCode | `opencode.json(c)` / `~/.config/opencode/opencode.json(c)` | **`mcp`** | type:"local", **command:[array]**, environment{} | type:"remote", `url`, headers | `opencode mcp add` (interactive only) |
35
+ | Cursor | `.cursor/mcp.json` / `~/.cursor/mcp.json` | `mcpServers` | command,args,env,cwd | `url`+headers (`${env:VAR}` interp.) | none (deep-links UNVERIFIED) |
36
+ | VS Code Copilot | `.vscode/mcp.json` / profile mcp.json / portable `.mcp.json` | **`servers`** (+inputs[]) | type:"stdio",command,args,env | type:"http"/"sse", url, headers | `copilot mcp add`; palette "MCP: Add Server" |
37
+ | Windsurf | `~/.codeium/windsurf/mcp_config.json` (global only) | `mcpServers` | command,args,env | **`serverUrl`** OR `url` + headers | none (Marketplace UI/deeplink) |
38
+ | Codex CLI | `~/.codex/config.toml` / project `.codex/config.toml` (trust-gated) | `[mcp_servers.<id>]` TOML | command,args,env,cwd | `url`, bearer_token_env_var, http_headers | `codex mcp add <n> --url \| -- cmd args` |
39
+ | Gemini CLI | `~/.gemini/settings.json` / `.gemini/settings.json` | `mcpServers` | command,args,env,cwd,trust | `httpUrl`(HTTP)/`url`(SSE)+headers | `gemini mcp add -s user\|project -t stdio\|sse\|http` |
40
+ | Antigravity | `~/.gemini/config/mcp_config.json` / `.agents/mcp_config.json` | `mcpServers` | command,args,env,cwd | **`serverUrl` MANDATORY — `url` rejected** + headers/oauth | none (`/mcp` overlay manager) |
41
+ | Zed | `~/.config/zed/settings.json` / `.zed/settings.json` | **`context_servers`** | command,args,env | `url`+headers (OAuth auto-prompt) | none (Settings UI writes file) |
42
+ | Kiro | `.kiro/settings/mcp.json` / `~/.kiro/settings/mcp.json` | `mcpServers` | command,args,env,disabled,autoApprove | `url`+headers+oauth | `/mcp add` (CLI session) |
43
+ | Trae IDE | `.trae/mcp.json` | `mcpServers` | command,args,env | url + type:"sse"/"http" | none (UI manual add) |
44
+
45
+ Restart semantics: full restart needed = Claude Desktop, Windsurf, Zed.
46
+ Hot-reload = Kiro, Gemini, Codex. Approval prompt on first detection =
47
+ Claude Code project-scope servers.
48
+
49
+ ## Sub-agent dispatch capability
50
+
51
+ | Harness | Native mechanism | Parallel background | Isolation for parallel edits |
52
+ |---|---|---|---|
53
+ | Claude Code | `Agent` tool + subagent_type; `.claude/agents/*.md` | Yes (default since v2.1.198; cap ~20) | BEST: `isolation: worktree` frontmatter; `/batch` |
54
+ | OpenCode | task/subagent tool + subagent_type | Yes (fg + background) | None in core → use file-ownership discipline or team-mode plugin worktrees |
55
+ | Codex CLI | model-mediated `spawn_agent`; max_depth=1 | Yes but children can't nest | None → prefer top-level parallel `codex exec` + manual git worktrees |
56
+ | Gemini CLI | subagents-as-tools; `@agent-name` | Yes BUT strictly hub-and-spoke (no nested calls) | None → restrict parallel workers to read-only roles unless given external worktrees |
57
+ | Cursor | Subagents w/ `is_background` frontmatter; `/multitask` | Yes | Opt-in per-subagent worktree or cloud VM |
58
+ | Antigravity | `invoke_subagent` (async by design); `/fork` | Yes | `/fork` workspace separation; per-subagent worktrees UNVERIFIED |
59
+
60
+ ## Headless invocation templates (fallback workers)
61
+
62
+ ```
63
+ claude claude -p "<prompt>" --output-format json --permission-mode acceptEdits
64
+ opencode opencode run "<prompt>" --auto --format json
65
+ codex codex exec --sandbox workspace-write --json -o <out-file> "<prompt>"
66
+ gemini gemini --output-format json "<prompt>"
67
+ agy agy -p --output-format json --print-timeout 15m "<prompt>"
68
+ ```
69
+
70
+ Completion signal = process exit (Claude documents 0/non-zero contract).
71
+ NEVER pass secrets as arguments. Feature-detect old binaries via `--version`.
72
+
73
+ ## Unknown platform procedure
74
+
75
+ 1. WEB SEARCH: `<platform> official docs MCP configuration` and
76
+ `<platform> agent skills install path`.
77
+ 2. Prefer official vendor domains over blog posts; note the date of sources.
78
+ 3. Present findings + proposed config diff to the user. [approval gate]
79
+ 4. Apply, verify, and offer to append findings to this table upstream.
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env node
2
+ // impact.mjs — reverse-dependency query: what is affected if <target> changes?
3
+ // Usage: node impact.mjs <tasks.yaml> <taskId-or-artifactPath>
4
+ // stdout: JSON {direct:[taskIds], transitive:[taskIds], artifacts:[paths]}
5
+ import { readFileSync } from 'node:fs';
6
+ import { parseYaml } from './lib/yaml.mjs';
7
+
8
+ const [, , file, target] = process.argv;
9
+ if (!file || !target) { console.error('usage: impact.mjs <tasks.yaml> <taskId-or-artifactPath>'); process.exit(4); }
10
+
11
+ const { data } = parseYaml(readFileSync(file, 'utf8'), { filename: file });
12
+ const tasks = data?.tasks;
13
+ if (!Array.isArray(tasks)) { console.error(`${file}: missing 'tasks:' sequence`); process.exit(4); }
14
+
15
+ // Resolve target to a seed set of task ids.
16
+ const byId = new Map(tasks.map((t) => [t.id, t]));
17
+ let seeds;
18
+ if (byId.has(target)) {
19
+ seeds = [target];
20
+ } else {
21
+ // Artifact-path mode: any task whose artifacts[] or file_ownership[] covers it.
22
+ seeds = tasks
23
+ .filter((t) => (t.artifacts ?? []).includes(target) || (t.file_ownership ?? []).includes(target))
24
+ .map((t) => t.id);
25
+ if (seeds.length === 0) { console.error(`no task claims '${target}' (not an id, artifact, or ownership glob)`); process.exit(4); }
26
+ }
27
+
28
+ // Reverse edges: dependents[prereq] = tasks that depend on it.
29
+ const dependents = new Map();
30
+ for (const t of tasks) {
31
+ for (const dep of t.depends_on ?? []) {
32
+ if (!dependents.has(dep)) dependents.set(dep, new Set());
33
+ dependents.get(dep).add(t.id);
34
+ }
35
+ }
36
+
37
+ // Direct = immediate dependents of seeds; transitive = everything beyond.
38
+ const direct = new Set();
39
+ const transitive = new Set();
40
+ for (const s of seeds) for (const d of dependents.get(s) ?? []) direct.add(d);
41
+ transitive.clear();
42
+ {
43
+ const seen = new Set([...seeds, ...direct]);
44
+ const f = [...direct];
45
+ while (f.length) {
46
+ const cur = f.pop();
47
+ for (const d of dependents.get(cur) ?? []) {
48
+ if (seen.has(d)) continue;
49
+ seen.add(d); transitive.add(d); f.push(d);
50
+ }
51
+ }
52
+ }
53
+
54
+ // Artifacts owned by affected tasks (what files the ripple touches).
55
+ const artifacts = new Set();
56
+ for (const id of [...direct, ...transitive]) {
57
+ for (const a of byId.get(id)?.artifacts ?? []) artifacts.add(a);
58
+ }
59
+
60
+ console.log(JSON.stringify({
61
+ direct: [...direct].sort(),
62
+ transitive: [...transitive].sort(),
63
+ artifacts: [...artifacts].sort(),
64
+ }, null, 2));
@@ -0,0 +1,128 @@
1
+ // graph.mjs — shared dependency-graph utilities for archgen scripts.
2
+ // WHY a lib: validate.mjs, next-tasks.mjs and verify-plan.mjs must agree on
3
+ // cycle detection and wave semantics; three copies would drift (Metis finding).
4
+
5
+ /** Build adjacency (prerequisite → dependents) + reverse maps from tasks.
6
+ * Normative semantics: depends_on lists PREREQUISITE ids; a task is ready iff
7
+ * every prerequisite is done; wave 1 = empty depends_on. */
8
+ export function buildGraph(tasks) {
9
+ /** @type {Map<string, string[]>} prereq -> [dependent ids] */
10
+ const dependents = new Map();
11
+ /** @type {Map<string, string[]>} id -> prerequisite ids */
12
+ const prerequisites = new Map();
13
+ const byId = new Map();
14
+ for (const t of tasks) {
15
+ if (byId.has(t.id)) throw new GraphError(`duplicate task id: ${t.id}`);
16
+ byId.set(t.id, t);
17
+ prerequisites.set(t.id, Array.isArray(t.depends_on) ? t.depends_on : []);
18
+ }
19
+ for (const t of tasks) {
20
+ for (const dep of prerequisites.get(t.id)) {
21
+ if (!byId.has(dep)) throw new GraphError(`dangling depends_on reference: '${t.id}' depends on unknown task '${dep}'`);
22
+ if (!dependents.has(dep)) dependents.set(dep, []);
23
+ dependents.get(dep).push(t.id);
24
+ }
25
+ }
26
+ return { byId, prerequisites, dependents };
27
+ }
28
+
29
+ export class GraphError extends Error {}
30
+
31
+ /** Return an array of ids forming a cycle (empty if acyclic). Iterative DFS. */
32
+ export function findCycle(prerequisites) {
33
+ const WHITE = 0, GRAY = 1, BLACK = 2;
34
+ const color = new Map();
35
+ const parent = new Map();
36
+ for (const id of prerequisites.keys()) color.set(id, WHITE);
37
+
38
+ for (const start of prerequisites.keys()) {
39
+ if (color.get(start) !== WHITE) continue;
40
+ const stack = [[start, 0]];
41
+ color.set(start, GRAY);
42
+ while (stack.length) {
43
+ const [id, pi] = stack[stack.length - 1];
44
+ const deps = prerequisites.get(id);
45
+ if (pi < deps.length) {
46
+ stack[stack.length - 1] = [id, pi + 1];
47
+ const d = deps[pi];
48
+ if (!color.has(d)) continue; // dangling handled elsewhere
49
+ if (color.get(d) === GRAY) {
50
+ // Found a back-edge: reconstruct the cycle path d ← id ← … ← d
51
+ const cycle = [d];
52
+ let cur = id;
53
+ while (cur !== d) { cycle.push(cur); cur = parent.get(cur); }
54
+ cycle.push(d);
55
+ return cycle.reverse();
56
+ }
57
+ if (color.get(d) === WHITE) { color.set(d, GRAY); parent.set(d, id); stack.push([d, 0]); }
58
+ } else {
59
+ color.set(id, BLACK);
60
+ stack.pop();
61
+ }
62
+ }
63
+ }
64
+ return [];
65
+ }
66
+
67
+ /** Topological waves over NOT-DONE tasks.
68
+ * @param {Map<string,any>} byId
69
+ * @param {Map<string,string[]>} prerequisites
70
+ * @returns {{waves: Array<Array<any>>, blockedByFailure: string[]}}
71
+ * Wave membership: every prerequisite is done. Tasks whose TRANSITIVE
72
+ * prerequisites include any failed task are excluded entirely and reported in
73
+ * blockedByFailure (no silent cascades — orchestrator re-plans around them). */
74
+ export function computeWaves(byId, prerequisites) {
75
+ const done = new Set();
76
+ const failed = new Set();
77
+ for (const [id, t] of byId) {
78
+ if (t.status === 'done') done.add(id);
79
+ if (t.status === 'failed') failed.add(id);
80
+ }
81
+ // Propagate failure transitively.
82
+ const blockedByFailure = new Set();
83
+ let changed = true;
84
+ while (changed) {
85
+ changed = false;
86
+ for (const [id, deps] of prerequisites) {
87
+ if (blockedByFailure.has(id) || failed.has(id)) continue;
88
+ if (deps.some((d) => failed.has(d) || blockedByFailure.has(d))) {
89
+ blockedByFailure.add(id); changed = true;
90
+ }
91
+ }
92
+ }
93
+
94
+ const remaining = [...byId.keys()].filter((id) =>
95
+ !done.has(id) && !failed.has(id) && !blockedByFailure.has(id));
96
+ const waves = [];
97
+ const satisfied = new Set(done);
98
+ let frontier = remaining.filter((id) => prerequisites.get(id).every((d) => satisfied.has(d)));
99
+ const queued = new Set();
100
+
101
+ while (frontier.length) {
102
+ frontier.sort(); // deterministic output for identical inputs
103
+ waves.push(frontier.map((id) => byId.get(id)));
104
+ for (const id of frontier) { satisfied.add(id); queued.add(id); }
105
+ const next = [];
106
+ for (const id of remaining) {
107
+ if (queued.has(id) || satisfied.has(id)) continue;
108
+ if (prerequisites.get(id).every((d) => satisfied.has(d))) next.push(id);
109
+ }
110
+ frontier = next;
111
+ }
112
+ return { waves, blockedByFailure: [...blockedByFailure].sort() };
113
+ }
114
+
115
+ /** First ownership conflict inside a single wave, or null.
116
+ * Ownership globs are treated as opaque strings for equality here — two tasks
117
+ * in the same wave must not claim the SAME literal glob (conservative rule that
118
+ * needs no glob-engine dependency). */
119
+ export function findOwnershipConflict(wave) {
120
+ const seen = new Map();
121
+ for (const t of wave) {
122
+ for (const g of t.file_ownership ?? []) {
123
+ if (seen.has(g)) return { glob: g, a: seen.get(g), b: t.id };
124
+ seen.set(g, t.id);
125
+ }
126
+ }
127
+ return null;
128
+ }