[Feature]: Multi-agent isolation protocol — process-level feature context without shared-state races

Đang mở
#4,128 2 bình luận 2 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

Đánh giá

Độ khó
4/5
Thời gian dự kiến
3-5 ngày
Mức phù hợp với người mới
55/100
Loại issue
Tính năng
Độ rõ ràng
Khá rõ ràng
Mức độ hoạt động
Ít trao đổi
Công nghệ
shell
Lĩnh vực
documentation, tooling

Hướng nghiên cứu

Bắt đầu với get_feature_paths trong common.sh, sau đó kiểm tra template của skill specify và bố cục tài liệu hiện có. Định nghĩa giao thức đa tác nhân trong docs/multi-agent.md, cập nhật hướng dẫn trong template và đánh giá hành vi tùy chọn của SPECIFY_NO_PERSIST. Công việc được xem là hoàn tất khi workflow được ghi trong tài liệu và template tránh việc ghi trực tiếp vào feature.json, đồng thời vẫn giữ nguyên các trường hợp tương thích ngược đã nêu.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

Problem Statement

When multiple AI agents run Spec Kit pipelines concurrently within the same repository checkout (e.g., Antigravity subagents, Claude Code sub-agents, or parallel Cursor Composer tabs), they share a single .specify/feature.json file as their feature context pointer. This creates a write-write race condition:

Timeline:
  t0  Agent-A: SPECIFY_FEATURE_DIRECTORY="specs/003-auth" → setup-plan.sh
      → get_feature_paths() persists "specs/003-auth" to feature.json  ✓
  t1  Agent-B: SPECIFY_FEATURE_DIRECTORY="specs/004-perf" → setup-tasks.sh
      → get_feature_paths() persists "specs/004-perf" to feature.json  ← overwrites A's value
  t2  Agent-A: (new process, no env var) → check-prerequisites.sh
      → reads feature.json → resolves "specs/004-perf"  ← WRONG FEATURE

The root issue: get_feature_paths() in common.sh (L191-192) always persists SPECIFY_FEATURE_DIRECTORY back to feature.json unless the caller explicitly passes --no-persist. Since most scripts (setup-plan.sh, setup-tasks.sh) call get_feature_paths without --no-persist, every agent invocation silently overwrites the shared singleton.

Impact
  • Silent cross-contamination: Agent B's plan/tasks get written into Agent A's feature directory (or vice versa) without any error signal.
  • Non-reproducible failures: The behavior depends on timing — sometimes it works, sometimes it doesn't, making debugging extremely difficult.
  • Blocks multi-agent orchestration: Features like /speckit-implement-waves (#3507), which propose running phases in parallel subagents, cannot work safely without solving this shared-state problem first.
Real-world reproduction

We encountered this in TTZip (a macOS archive utility, 525+ tests, 28 design patterns) while running Antigravity subagents to parallelize a sorting-bugfix TDD suite alongside a 7z compression optimization. Both agents used SPECIFY_FEATURE_DIRECTORY correctly in their own processes, but the persist-on-read side effect in get_feature_paths caused each agent to clobber the other's feature.json entry on every script call.


Root Cause Analysis

The feature resolution chain in common.sh get_feature_paths() (L163-231) has a correct read priority:

1. SPECIFY_FEATURE_DIRECTORY env var  (explicit override)
2. .specify/feature.json              (persisted fallback)
3. Error                              (no context)

But it has an unconditional write side effect on the env-var branch (L191-192):

if [[ "$no_persist" != true ]]; then
    _persist_feature_json "$repo_root" "$SPECIFY_FEATURE_DIRECTORY"
fi

The --no-persist guard (added in #3025) is a function-level parameter, not an environment-level control. Scripts that are "just resolving paths" but don't know they should pass --no-persist (like setup-plan.sh, setup-tasks.sh) trigger the persist unconditionally.

What already works

Credit to the maintainers — the infrastructure for multi-agent isolation is already in place:

Mechanism Status Issue
SPECIFY_FEATURE_DIRECTORY env var priority ✅ Working
--no-persist read-only resolution ✅ Working #3025
CURRENT_BRANCH fallback from feature dir basename ✅ Working #3026
SPECIFY_INIT_DIR for monorepo project scoping ✅ Working
Parser fallback chain (jq → python3 → grep/sed) ✅ Working #3304

What's missing is the guidance layer: documentation, agent skill instructions, and an environment-level no-persist toggle.


Proposed Solution

1. Official multi-agent documentation (docs/multi-agent.md)

A new document covering:

  • The race condition scenario (as above)
  • The Multi-Agent Isolation Protocol: always inject SPECIFY_FEATURE_DIRECTORY per-process, never rely on feature.json for read
  • Integration-specific examples (Antigravity subagents, Claude Code sub-agents, Cursor multi-tab, CI matrix)
  • FAQ: "Do I need git worktrees?" → No, env-var isolation is sufficient for same-checkout concurrency
2. Update agent skill templates to stop instructing direct feature.json writes

Currently, the specify command template (the upstream equivalent of speckit-specify/SKILL.md) instructs agents to:

Persist the resolved path to .specify/feature.json: {"feature_directory": "<resolved feature dir>"}

This instruction should be replaced with:

Pass the resolved feature directory to downstream commands via SPECIFY_FEATURE_DIRECTORY environment variable prefix. Example: SPECIFY_FEATURE_DIRECTORY="specs/003-auth" .specify/scripts/bash/setup-plan.sh --json

The feature.json persistence should remain as an automatic side effect of get_feature_paths() for single-agent backward compatibility, but agents should not be told to write it directly (which bypasses the script's own idempotency guards in _persist_feature_json).

3. (Optional) SPECIFY_NO_PERSIST environment variable

Add an environment-level equivalent of the --no-persist function parameter:

# In get_feature_paths(), after the --no-persist argument check (L167-171):
if [[ "${SPECIFY_NO_PERSIST:-}" == "1" || "${SPECIFY_NO_PERSIST:-}" == "true" ]]; then
    no_persist=true
fi

This allows CI pipelines and agent orchestrators to set SPECIFY_NO_PERSIST=1 globally, ensuring that no script invocation can accidentally write feature.json — even scripts that don't pass --no-persist internally.


Backward Compatibility

This proposal is fully backward compatible:

Scenario Before After
Single agent, no env var Reads feature.json Identical behavior
Single agent, with env var Reads env var, persists to feature.json Identical behavior
Multi-agent, each sets env var Race on feature.json (bug) Each agent's reads are short-circuited by env var; persistence is harmless
Multi-agent + SPECIFY_NO_PERSIST=1 N/A No feature.json writes at all
specify integration upgrade Overwrites managed files docs/multi-agent.md is not in manifest; protocol rules live in user-space

No existing scripts, templates, or workflows change behavior. The persist side effect is still there (it's a "last writer wins" overwrite that's harmless when every reader uses env vars). SPECIFY_NO_PERSIST is strictly additive.


Reference Implementation

We've been running this protocol in production at TTZip with Antigravity (Google DeepMind's agentic coding tool) subagents. Our implementation consists of:

  1. Project-level rule file (.agents/rules/speckit-multiagent.md): Instructs all agents to inject SPECIFY_FEATURE_DIRECTORY per-process and never read/write feature.json directly.
  2. Global user rule: Gates (hard state machine gating) that prevent any agent from writing production code before spec/plan/tasks artifacts exist under the declared feature directory.
  3. Concurrent verification: Validated that two agents operating on specs/003-sorting-fix/ and specs/006-7z-conquest/ simultaneously produce zero cross-contamination.

The protocol adds zero overhead to single-agent workflows and requires no upstream code changes to function — it's purely a documentation and guidance contribution. The optional SPECIFY_NO_PERSIST env var is a small, additive improvement to common.sh.


Related Issues

  • #3507 — /speckit-implement-waves: Needs this isolation protocol as a prerequisite for safe parallel phase execution
  • #1476 — Git worktree isolation: Our approach is complementary (env-var isolation within a single checkout vs. filesystem isolation across worktrees)
  • #3025 — --no-persist for read-only resolution: Foundation we build on
  • #3026 — CURRENT_BRANCH fallback: Foundation we build on
  • #752 — Claude Code subagent feature execution: Would benefit from this protocol

Component

Core scripts (common.sh), Documentation, Agent skill templates

Ngôn ngữ chính
Python
Star
138k
Fork
12.4k
Merge trung bình
3 ngày 6 giờ
Pull request đã merge (30 ngày)
136

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của github/spec-kit

Tất cả issue của github/spec-kit

Issue tương tự

Thêm issue về Python

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.