@zigrivers/scaffold 3.32.0 → 3.33.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/README.md +42 -19
- package/content/guides/knowledge-freshness/.diagrams/diagram-0.svg +1 -1
- package/content/guides/knowledge-freshness/.diagrams/manifest.json +1 -1
- package/content/guides/knowledge-freshness/index.html +9 -5
- package/content/guides/knowledge-freshness/index.md +5 -4
- package/content/guides/multi-agent/index.html +16 -15
- package/content/guides/multi-agent/index.md +16 -15
- package/content/guides/pipeline/index.html +2 -2
- package/content/guides/pipeline/index.md +2 -2
- package/content/knowledge/execution/worktree-management.md +4 -4
- package/content/knowledge/mcp-server/mcp-authentication.md +100 -0
- package/content/knowledge/mcp-server/mcp-deployment-patterns.md +119 -0
- package/content/knowledge/mcp-server/mcp-error-handling.md +131 -0
- package/content/knowledge/mcp-server/mcp-observability.md +125 -0
- package/content/knowledge/mcp-server/mcp-prompt-primitives.md +119 -0
- package/content/knowledge/mcp-server/mcp-protocol-fundamentals.md +130 -0
- package/content/knowledge/mcp-server/mcp-resource-design.md +111 -0
- package/content/knowledge/mcp-server/mcp-sdk-selection.md +136 -0
- package/content/knowledge/mcp-server/mcp-testing-strategies.md +127 -0
- package/content/knowledge/mcp-server/mcp-tool-design.md +125 -0
- package/content/knowledge/mcp-server/mcp-transport-patterns.md +122 -0
- package/content/knowledge/mcp-server/mcp-versioning.md +115 -0
- package/content/methodology/custom-defaults.yml +2 -0
- package/content/methodology/deep.yml +2 -0
- package/content/methodology/mcp-server-overlay.yml +88 -0
- package/content/methodology/mvp.yml +2 -0
- package/content/pipeline/build/multi-agent-resume.md +107 -11
- package/content/pipeline/build/multi-agent-start.md +104 -11
- package/content/pipeline/build/single-agent-resume.md +74 -8
- package/content/pipeline/build/single-agent-start.md +69 -12
- package/content/pipeline/environment/git-workflow.md +8 -2
- package/content/pipeline/finalization/materialize-plan-to-beads.md +473 -0
- package/content/pipeline/foundation/beads.md +6 -0
- package/content/pipeline/planning/implementation-plan-review.md +25 -0
- package/content/pipeline/planning/implementation-plan.md +75 -1
- package/content/pipeline/specification/mcp-tool-resource-contract.md +77 -0
- package/dist/cli/commands/adopt.d.ts.map +1 -1
- package/dist/cli/commands/adopt.js +33 -1
- package/dist/cli/commands/adopt.js.map +1 -1
- package/dist/cli/commands/init.d.ts +6 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +46 -3
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/init-flag-families.d.ts +6 -1
- package/dist/cli/init-flag-families.d.ts.map +1 -1
- package/dist/cli/init-flag-families.js +59 -2
- package/dist/cli/init-flag-families.js.map +1 -1
- package/dist/cli/init-flag-families.test.js +86 -1
- package/dist/cli/init-flag-families.test.js.map +1 -1
- package/dist/config/schema.d.ts +2310 -126
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +26 -1
- package/dist/config/schema.js.map +1 -1
- package/dist/config/schema.test.js +75 -2
- package/dist/config/schema.test.js.map +1 -1
- package/dist/config/validators/index.d.ts.map +1 -1
- package/dist/config/validators/index.js +2 -0
- package/dist/config/validators/index.js.map +1 -1
- package/dist/config/validators/mcp-server.d.ts +4 -0
- package/dist/config/validators/mcp-server.d.ts.map +1 -0
- package/dist/config/validators/mcp-server.js +37 -0
- package/dist/config/validators/mcp-server.js.map +1 -0
- package/dist/config/validators/mcp-server.test.d.ts +2 -0
- package/dist/config/validators/mcp-server.test.d.ts.map +1 -0
- package/dist/config/validators/mcp-server.test.js +47 -0
- package/dist/config/validators/mcp-server.test.js.map +1 -0
- package/dist/core/assembly/materialize-plan-to-beads-assembly.test.d.ts +2 -0
- package/dist/core/assembly/materialize-plan-to-beads-assembly.test.d.ts.map +1 -0
- package/dist/core/assembly/materialize-plan-to-beads-assembly.test.js +75 -0
- package/dist/core/assembly/materialize-plan-to-beads-assembly.test.js.map +1 -0
- package/dist/e2e/project-type-overlays.test.js +83 -0
- package/dist/e2e/project-type-overlays.test.js.map +1 -1
- package/dist/project/adopt.d.ts.map +1 -1
- package/dist/project/adopt.js +3 -1
- package/dist/project/adopt.js.map +1 -1
- package/dist/project/detectors/coverage.test.js +1 -0
- package/dist/project/detectors/coverage.test.js.map +1 -1
- package/dist/project/detectors/disambiguate.d.ts.map +1 -1
- package/dist/project/detectors/disambiguate.js +6 -1
- package/dist/project/detectors/disambiguate.js.map +1 -1
- package/dist/project/detectors/disambiguate.test.js +18 -0
- package/dist/project/detectors/disambiguate.test.js.map +1 -1
- package/dist/project/detectors/index.d.ts.map +1 -1
- package/dist/project/detectors/index.js +2 -1
- package/dist/project/detectors/index.js.map +1 -1
- package/dist/project/detectors/mcp-server.d.ts +4 -0
- package/dist/project/detectors/mcp-server.d.ts.map +1 -0
- package/dist/project/detectors/mcp-server.js +91 -0
- package/dist/project/detectors/mcp-server.js.map +1 -0
- package/dist/project/detectors/mcp-server.test.d.ts +2 -0
- package/dist/project/detectors/mcp-server.test.d.ts.map +1 -0
- package/dist/project/detectors/mcp-server.test.js +115 -0
- package/dist/project/detectors/mcp-server.test.js.map +1 -0
- package/dist/project/detectors/types.d.ts +6 -2
- package/dist/project/detectors/types.d.ts.map +1 -1
- package/dist/project/detectors/types.js.map +1 -1
- package/dist/project/gitignore.d.ts.map +1 -1
- package/dist/project/gitignore.js +4 -0
- package/dist/project/gitignore.js.map +1 -1
- package/dist/project/gitignore.test.js +1 -0
- package/dist/project/gitignore.test.js.map +1 -1
- package/dist/types/config.d.ts +8 -1
- package/dist/types/config.d.ts.map +1 -1
- package/dist/wizard/copy/core.d.ts.map +1 -1
- package/dist/wizard/copy/core.js +4 -0
- package/dist/wizard/copy/core.js.map +1 -1
- package/dist/wizard/copy/index.d.ts.map +1 -1
- package/dist/wizard/copy/index.js +2 -0
- package/dist/wizard/copy/index.js.map +1 -1
- package/dist/wizard/copy/mcp-server.d.ts +3 -0
- package/dist/wizard/copy/mcp-server.d.ts.map +1 -0
- package/dist/wizard/copy/mcp-server.js +40 -0
- package/dist/wizard/copy/mcp-server.js.map +1 -0
- package/dist/wizard/copy/types.d.ts +5 -1
- package/dist/wizard/copy/types.d.ts.map +1 -1
- package/dist/wizard/flags.d.ts +9 -1
- package/dist/wizard/flags.d.ts.map +1 -1
- package/dist/wizard/questions.d.ts +4 -2
- package/dist/wizard/questions.d.ts.map +1 -1
- package/dist/wizard/questions.js +37 -0
- package/dist/wizard/questions.js.map +1 -1
- package/dist/wizard/questions.test.js +107 -0
- package/dist/wizard/questions.test.js.map +1 -1
- package/dist/wizard/wizard.d.ts +3 -2
- package/dist/wizard/wizard.d.ts.map +1 -1
- package/dist/wizard/wizard.js +3 -1
- package/dist/wizard/wizard.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mcp-versioning
|
|
3
|
+
description: MCP protocol version negotiation, MCP-Protocol-Version HTTP header, capability-based feature detection, server versioning strategy, and backwards compatibility
|
|
4
|
+
topics: [mcp, versioning, protocol-version, backwards-compatibility, capability-negotiation]
|
|
5
|
+
volatility: stable
|
|
6
|
+
last-reviewed: null
|
|
7
|
+
version-pin: 'MCP spec 2025-11-25'
|
|
8
|
+
sources:
|
|
9
|
+
- url: https://modelcontextprotocol.io/specification/2025-11-25/basic/lifecycle
|
|
10
|
+
- url: https://modelcontextprotocol.io/specification/2025-11-25/basic/transports
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
MCP uses calendar-versioned protocol strings and capability-based feature detection. Understand both mechanisms to build servers that work with current clients and remain compatible as the spec evolves.
|
|
14
|
+
|
|
15
|
+
## Summary
|
|
16
|
+
|
|
17
|
+
Protocol versions are date strings (e.g., `2025-11-25`). The client proposes a version in `initialize`; the server echoes it or responds with its preferred version. If versions are incompatible, the client disconnects. HTTP clients MUST include `MCP-Protocol-Version: <negotiated-version>` on all subsequent requests. Feature availability is determined by capability negotiation, not version numbers alone. For your server's own versioning, use semantic versioning; keep the `serverInfo.version` field current and stable across protocol version changes.
|
|
18
|
+
|
|
19
|
+
## Deep Guidance
|
|
20
|
+
|
|
21
|
+
### Protocol version strings
|
|
22
|
+
|
|
23
|
+
MCP protocol versions are ISO 8601 calendar dates: `2025-11-25`, `2025-06-18`, `2025-03-26`, `2024-11-05`. Current production version is `2025-11-25`. Always send the latest version you support in the `initialize` request — the server will downgrade if needed.
|
|
24
|
+
|
|
25
|
+
Version negotiation in the `initialize` handshake:
|
|
26
|
+
1. Client sends `"protocolVersion": "2025-11-25"` (its latest supported version).
|
|
27
|
+
2. If the server supports `2025-11-25`, it responds with `"protocolVersion": "2025-11-25"`.
|
|
28
|
+
3. If the server only supports `2025-03-26`, it responds with `"protocolVersion": "2025-03-26"`.
|
|
29
|
+
4. The client checks if it supports the server's response version. If not, it disconnects.
|
|
30
|
+
|
|
31
|
+
This ensures both sides agree on a common protocol dialect before any other messages are exchanged.
|
|
32
|
+
|
|
33
|
+
### MCP-Protocol-Version HTTP header
|
|
34
|
+
|
|
35
|
+
After initialization, HTTP clients MUST send `MCP-Protocol-Version: <negotiated-version>` on every subsequent request:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
POST /mcp HTTP/1.1
|
|
39
|
+
Host: mcp.example.com
|
|
40
|
+
Content-Type: application/json
|
|
41
|
+
Accept: application/json, text/event-stream
|
|
42
|
+
MCP-Protocol-Version: 2025-11-25
|
|
43
|
+
Mcp-Session-Id: abc123
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Servers use this header to handle requests differently based on protocol version when supporting multiple versions simultaneously. If a server receives no `MCP-Protocol-Version` header, the spec says to assume `2025-03-26` for backwards compatibility. Servers MUST return `400 Bad Request` for unsupported or invalid version header values.
|
|
47
|
+
|
|
48
|
+
### Capability-based feature detection
|
|
49
|
+
|
|
50
|
+
Do not version-gate features solely on protocol version numbers. Use capability negotiation instead. A server supporting `2025-11-25` may not declare the `prompts` capability — that means prompts are not available regardless of protocol version.
|
|
51
|
+
|
|
52
|
+
The correct pattern for clients: check whether the server declared the capability before calling the corresponding methods. A client that calls `tools/list` without checking whether the server declared `tools` capability will receive a protocol error. The `initialize` response is the authoritative source of truth for what a server supports.
|
|
53
|
+
|
|
54
|
+
For servers: declare only the capabilities you actually implement. Over-declaring capabilities (e.g., declaring `resources: { subscribe: true }` but not handling `resources/subscribe`) will cause client errors and poor UX.
|
|
55
|
+
|
|
56
|
+
### Evolving your server's capabilities over versions
|
|
57
|
+
|
|
58
|
+
When you add a new capability to your server (e.g., adding resource support to a tools-only server):
|
|
59
|
+
- Add the capability to your `initialize` response immediately.
|
|
60
|
+
- The capability declaration is backwards compatible — old clients that don't use resources will simply not call `resources/list`.
|
|
61
|
+
- Do not bump your `serverInfo.version` for protocol-level changes; that field tracks your server's own software version.
|
|
62
|
+
|
|
63
|
+
When you remove a capability (uncommon but possible):
|
|
64
|
+
- Remove it from the `initialize` response.
|
|
65
|
+
- Any client that was relying on it will receive a protocol error when they call the now-unsupported method.
|
|
66
|
+
- Consider maintaining the capability with a deprecation notice in the server's `instructions` field before fully removing it.
|
|
67
|
+
|
|
68
|
+
### Server software versioning
|
|
69
|
+
|
|
70
|
+
The `serverInfo.version` in `initialize` is your server's semantic version (e.g., `"1.3.0"`), independent of the MCP protocol version. Follow semantic versioning:
|
|
71
|
+
- **Patch** (1.0.x): bug fixes, no schema changes, no capability changes.
|
|
72
|
+
- **Minor** (1.x.0): new tools/resources/prompts added, existing ones unchanged.
|
|
73
|
+
- **Major** (x.0.0): removed or renamed tools/resources/prompts, breaking schema changes.
|
|
74
|
+
|
|
75
|
+
Breaking changes in tool `inputSchema` or resource URI patterns are breaking changes for MCP clients that have auto-discovered and cached your server's schema. Treat them as major version bumps and communicate them in advance.
|
|
76
|
+
|
|
77
|
+
### Supporting multiple protocol versions simultaneously
|
|
78
|
+
|
|
79
|
+
If you need to serve both old (2024-11-05 HTTP+SSE) and new (2025-11-25 Streamable HTTP) clients:
|
|
80
|
+
- Keep the old SSE GET endpoint and POST endpoint running alongside the new MCP endpoint.
|
|
81
|
+
- Use the `MCP-Protocol-Version` header to route behavior within the Streamable HTTP path.
|
|
82
|
+
- Set a deprecation date for old transport support and communicate it in the `serverInfo` description or via documentation.
|
|
83
|
+
|
|
84
|
+
For servers that only need to support the latest spec, target `2025-11-25` and do not implement the deprecated HTTP+SSE transport. New clients target the current spec; support for the old transport is only needed if you have existing clients that have not yet migrated.
|
|
85
|
+
|
|
86
|
+
### Spec evolution cadence
|
|
87
|
+
|
|
88
|
+
The MCP spec has evolved on roughly a quarterly cadence: `2024-11-05` (initial), `2025-03-26` (Streamable HTTP introduction), `2025-06-18`, `2025-11-25` (current). Major changes between versions: `2024-11-05 → 2025-03-26` introduced Streamable HTTP, deprecating HTTP+SSE. `2025-03-26 → 2025-06-18` added `outputSchema` for tools, `structuredContent`, audio content type, `title` fields, and the `elicitation` client capability. `2025-06-18 → 2025-11-25` added OIDC Discovery 1.0 support; aligned OAuth Protected Resource Metadata to RFC 9728 (`WWW-Authenticate` header now optional with `.well-known` fallback); incremental scope consent and Client ID Metadata Documents for client registration; `icons` metadata on tools/resources/prompts; JSON Schema 2020-12 as the default dialect; input validation errors explicitly directed as Tool Execution Errors (`isError`) for model self-correction; Streamable HTTP servers MUST respond HTTP 403 for invalid Origin headers; stdio servers MAY use stderr for all logging; elicitation gains URL-mode, titled/untitled enums, and primitive default values; sampling gains `tools`/`toolChoice` support; experimental `tasks` feature for durable requests with polling. Watch the spec changelog (https://modelcontextprotocol.io) for new capabilities that may benefit your server.
|
|
89
|
+
|
|
90
|
+
### Backwards compatibility checklist
|
|
91
|
+
|
|
92
|
+
When releasing a new server version, verify these backwards compatibility invariants before shipping:
|
|
93
|
+
|
|
94
|
+
1. **No renamed tools**: renaming a tool (e.g., `search_files` → `find_files`) is a breaking change. Existing clients with auto-approved tool calls will fail silently. Use the old name as an alias or bump major version with advance notice.
|
|
95
|
+
2. **No removed required input fields**: removing a required field from `inputSchema` is non-breaking (callers can stop providing it); adding a new required field IS breaking (callers that don't provide it will receive validation errors).
|
|
96
|
+
3. **No resource URI pattern changes**: changing `file://{path}` to `file://workspace/{path}` breaks all existing resource subscriptions and saved URIs. Treat as a major version change.
|
|
97
|
+
4. **No prompt argument removals**: removing a declared prompt argument breaks clients that pass that argument.
|
|
98
|
+
5. **No capability downgrades without communication**: removing `resources: { subscribe: true }` when clients have active subscriptions causes silent failures.
|
|
99
|
+
|
|
100
|
+
For patch and minor releases, adding new optional tool parameters, new tools, new resources, or new prompts is always backwards compatible — existing callers ignore what they don't use.
|
|
101
|
+
|
|
102
|
+
### Version signaling in serverInfo
|
|
103
|
+
|
|
104
|
+
Use the `serverInfo.version` field as a machine-readable signal for clients that cache schemas:
|
|
105
|
+
|
|
106
|
+
```json
|
|
107
|
+
{
|
|
108
|
+
"serverInfo": {
|
|
109
|
+
"name": "my-mcp-server",
|
|
110
|
+
"version": "2.1.0"
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Clients can cache tool/resource schemas keyed by `(serverInfo.name, serverInfo.version)`. When the server bumps its version, clients re-fetch schemas rather than serving stale cached definitions. This pattern is especially important for IDE integrations and agent frameworks that pre-load tool definitions at startup.
|
|
@@ -43,6 +43,7 @@ steps:
|
|
|
43
43
|
database-schema: { enabled: true, conditional: "if-needed" }
|
|
44
44
|
review-database: { enabled: true, conditional: "if-needed" }
|
|
45
45
|
api-contracts: { enabled: true, conditional: "if-needed" }
|
|
46
|
+
mcp-tool-resource-contract: { enabled: false }
|
|
46
47
|
review-api: { enabled: true, conditional: "if-needed" }
|
|
47
48
|
ux-spec: { enabled: true, conditional: "if-needed" }
|
|
48
49
|
review-ux: { enabled: true, conditional: "if-needed" }
|
|
@@ -74,6 +75,7 @@ steps:
|
|
|
74
75
|
apply-fixes-and-freeze: { enabled: true }
|
|
75
76
|
developer-onboarding-guide: { enabled: true }
|
|
76
77
|
implementation-playbook: { enabled: true }
|
|
78
|
+
materialize-plan-to-beads: { enabled: true, conditional: "if-needed" }
|
|
77
79
|
# Phase 15 — Build (build) — stateless, on-demand execution steps
|
|
78
80
|
single-agent-start: { enabled: true }
|
|
79
81
|
single-agent-resume: { enabled: true }
|
|
@@ -42,6 +42,7 @@ steps:
|
|
|
42
42
|
database-schema: { enabled: true, conditional: "if-needed" }
|
|
43
43
|
review-database: { enabled: true, conditional: "if-needed" }
|
|
44
44
|
api-contracts: { enabled: true, conditional: "if-needed" }
|
|
45
|
+
mcp-tool-resource-contract: { enabled: false }
|
|
45
46
|
review-api: { enabled: true, conditional: "if-needed" }
|
|
46
47
|
ux-spec: { enabled: true, conditional: "if-needed" }
|
|
47
48
|
review-ux: { enabled: true, conditional: "if-needed" }
|
|
@@ -73,6 +74,7 @@ steps:
|
|
|
73
74
|
apply-fixes-and-freeze: { enabled: true }
|
|
74
75
|
developer-onboarding-guide: { enabled: true }
|
|
75
76
|
implementation-playbook: { enabled: true }
|
|
77
|
+
materialize-plan-to-beads: { enabled: true, conditional: "if-needed" }
|
|
76
78
|
# Phase 15 — Build (build) — stateless, on-demand execution steps
|
|
77
79
|
single-agent-start: { enabled: true }
|
|
78
80
|
single-agent-resume: { enabled: true }
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# methodology/mcp-server-overlay.yml
|
|
2
|
+
name: mcp-server
|
|
3
|
+
description: >
|
|
4
|
+
MCP Server overlay — an MCP server has no UI, so the design-system and UX
|
|
5
|
+
steps are disabled. database-schema/review-database stay available
|
|
6
|
+
(if-needed) for servers that persist resources/state. The
|
|
7
|
+
mcp-tool-resource-contract step is enabled (if-needed) for specifying MCP
|
|
8
|
+
tool/resource/prompt schemas. MCP domain knowledge (protocol, SDK, transport,
|
|
9
|
+
tool/resource design, auth, testing, deployment, observability, versioning)
|
|
10
|
+
is injected into the relevant pipeline steps.
|
|
11
|
+
project-type: mcp-server
|
|
12
|
+
|
|
13
|
+
step-overrides:
|
|
14
|
+
# No UI surface — disable design/UX steps entirely.
|
|
15
|
+
design-system: { enabled: false }
|
|
16
|
+
ux-spec: { enabled: false }
|
|
17
|
+
review-ux: { enabled: false }
|
|
18
|
+
# Stateful servers may persist resources; keep available but skippable.
|
|
19
|
+
database-schema: { enabled: true, conditional: "if-needed" }
|
|
20
|
+
review-database: { enabled: true, conditional: "if-needed" }
|
|
21
|
+
# MCP-specific spec step — enabled for mcp-server projects.
|
|
22
|
+
mcp-tool-resource-contract: { enabled: true, conditional: "if-needed" }
|
|
23
|
+
|
|
24
|
+
# ---------------------------------------------------------------------------
|
|
25
|
+
# knowledge-overrides
|
|
26
|
+
# ---------------------------------------------------------------------------
|
|
27
|
+
# Inject MCP domain expertise into existing pipeline steps so that MCP
|
|
28
|
+
# protocol, SDK, transport, tool/resource design, auth, testing, deployment,
|
|
29
|
+
# observability, and versioning knowledge is available during prompt assembly.
|
|
30
|
+
knowledge-overrides:
|
|
31
|
+
# Foundation
|
|
32
|
+
tech-stack:
|
|
33
|
+
append: [mcp-protocol-fundamentals, mcp-sdk-selection, mcp-transport-patterns]
|
|
34
|
+
tdd:
|
|
35
|
+
append: [mcp-testing-strategies]
|
|
36
|
+
|
|
37
|
+
# Architecture & Decisions
|
|
38
|
+
system-architecture:
|
|
39
|
+
append: [mcp-protocol-fundamentals, mcp-transport-patterns, mcp-tool-design, mcp-resource-design]
|
|
40
|
+
adrs:
|
|
41
|
+
append: [mcp-sdk-selection, mcp-transport-patterns]
|
|
42
|
+
|
|
43
|
+
# Specifications
|
|
44
|
+
api-contracts:
|
|
45
|
+
append: [mcp-tool-design, mcp-resource-design, mcp-error-handling]
|
|
46
|
+
# mcp-tool-resource-contract knowledge is already declared in the step's own
|
|
47
|
+
# frontmatter knowledge-base ([mcp-tool-design, mcp-resource-design,
|
|
48
|
+
# mcp-prompt-primitives, mcp-error-handling]); no overlay override needed.
|
|
49
|
+
database-schema:
|
|
50
|
+
append: [mcp-resource-design]
|
|
51
|
+
|
|
52
|
+
# Testing
|
|
53
|
+
add-e2e-testing:
|
|
54
|
+
append: [mcp-testing-strategies]
|
|
55
|
+
|
|
56
|
+
# Quality Gates
|
|
57
|
+
security:
|
|
58
|
+
append: [mcp-authentication]
|
|
59
|
+
review-security:
|
|
60
|
+
append: [mcp-authentication]
|
|
61
|
+
operations:
|
|
62
|
+
append: [mcp-deployment-patterns, mcp-observability, mcp-versioning]
|
|
63
|
+
review-operations:
|
|
64
|
+
append: [mcp-deployment-patterns, mcp-observability, mcp-versioning]
|
|
65
|
+
|
|
66
|
+
# Reviews
|
|
67
|
+
review-architecture:
|
|
68
|
+
append: [mcp-transport-patterns, mcp-tool-design, mcp-resource-design]
|
|
69
|
+
|
|
70
|
+
# ---------------------------------------------------------------------------
|
|
71
|
+
# reads-overrides
|
|
72
|
+
# ---------------------------------------------------------------------------
|
|
73
|
+
# Wire docs/mcp-contract.md (output of mcp-tool-resource-contract) into
|
|
74
|
+
# downstream steps that need MCP auth/validation/error contracts.
|
|
75
|
+
# Uses append-only so non-MCP steps are unaffected when the overlay is absent.
|
|
76
|
+
reads-overrides:
|
|
77
|
+
# Security review: MCP auth/error contracts are security-relevant
|
|
78
|
+
security:
|
|
79
|
+
append: [mcp-tool-resource-contract]
|
|
80
|
+
review-security:
|
|
81
|
+
append: [mcp-tool-resource-contract]
|
|
82
|
+
# Test generation: test the tools/resources against the contract
|
|
83
|
+
create-evals:
|
|
84
|
+
append: [mcp-tool-resource-contract]
|
|
85
|
+
story-tests:
|
|
86
|
+
append: [mcp-tool-resource-contract]
|
|
87
|
+
tdd:
|
|
88
|
+
append: [mcp-tool-resource-contract]
|
|
@@ -42,6 +42,7 @@ steps:
|
|
|
42
42
|
database-schema: { enabled: false }
|
|
43
43
|
review-database: { enabled: false }
|
|
44
44
|
api-contracts: { enabled: false }
|
|
45
|
+
mcp-tool-resource-contract: { enabled: false }
|
|
45
46
|
review-api: { enabled: false }
|
|
46
47
|
ux-spec: { enabled: false }
|
|
47
48
|
review-ux: { enabled: false }
|
|
@@ -73,6 +74,7 @@ steps:
|
|
|
73
74
|
apply-fixes-and-freeze: { enabled: false }
|
|
74
75
|
developer-onboarding-guide: { enabled: false }
|
|
75
76
|
implementation-playbook: { enabled: true }
|
|
77
|
+
materialize-plan-to-beads: { enabled: false }
|
|
76
78
|
# Phase 15 — Build (build) — stateless, on-demand execution steps
|
|
77
79
|
single-agent-start: { enabled: true }
|
|
78
80
|
single-agent-resume: { enabled: true }
|
|
@@ -119,17 +119,113 @@ Recover your context by checking the current state of work:
|
|
|
119
119
|
|
|
120
120
|
### Beads Recovery
|
|
121
121
|
|
|
122
|
-
|
|
123
|
-
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
122
|
+
The implementation plan is materialized into Beads issues by
|
|
123
|
+
`/scaffold:materialize-plan-to-beads` before the build phase. A resumed build
|
|
124
|
+
runs the **same defensive preflight** as the start prompt — it never claims
|
|
125
|
+
against an empty or stale tracker. Under multi-agent concurrency,
|
|
126
|
+
materialization is **orchestrator-only** and runs **once per wave under a
|
|
127
|
+
merge-slot lock**; workers never materialize and must wait for a run-stamped
|
|
128
|
+
completion signal before their first claim.
|
|
129
|
+
|
|
130
|
+
**Step 1 — compute `beads_usable`.** `beads_usable` is true only when **all**
|
|
131
|
+
hold: `.beads/` exists, `bd` is on `PATH`, `bd version` parses to **≥ 1.0.5**
|
|
132
|
+
(using a macOS/BSD-safe numeric compare — split major/minor/patch and compare
|
|
133
|
+
numerically, never rely on GNU `sort -V`), and `jq` is on `PATH`. Never write
|
|
134
|
+
`[ -d .beads ] && bd …` as a whole command — it returns exit 1 when `.beads/` is
|
|
135
|
+
absent and breaks callers under `set -e`; use an `if`.
|
|
136
|
+
|
|
137
|
+
**Step 2 — route on the decision table** (this is what prevents the "empty
|
|
138
|
+
tracker looks done" bug):
|
|
139
|
+
|
|
140
|
+
| Condition | Action |
|
|
141
|
+
|---|---|
|
|
142
|
+
| `.beads/` **absent** | Non-Beads project → drive the loop from the markdown playbook/plan (see "Markdown fallback" below). Do **not** call `bd`. |
|
|
143
|
+
| `.beads/` present but `beads_usable` is false (`bd`/`jq` missing or `bd` < 1.0.5) | **Fail closed.** Stop and tell the user to install/upgrade `bd` (≥ v1.0.5) and `jq`. Do **not** markdown-fall-back — Beads may already hold execution state. |
|
|
144
|
+
| `beads_usable`, plan has **no** stable IDs **and** Beads holds no plan-derived issues and no non-bootstrap claimed/closed work | Genuinely legacy plan → markdown loop, emit "re-run planning to assign stable task IDs". Do **not** claim. |
|
|
145
|
+
| `beads_usable`, plan has no stable IDs **but** Beads already holds plausible build work | **Fail closed** — markdown would bypass existing execution state. |
|
|
146
|
+
| `beads_usable`, contract **partially present or malformed** | **Fail closed.** Do **not** markdown-fall-back. Require planning to be re-run/fixed. |
|
|
147
|
+
| `beads_usable` **and a valid stable-ID contract** | **Resume your own task; orchestrator materializes once under the lock; workers wait; then claim** (see Step 3). |
|
|
148
|
+
|
|
149
|
+
**Step 3 — `beads_usable` + valid contract:**
|
|
150
|
+
|
|
151
|
+
**Two distinct identities.** The merge-slot needs a **per-process unique** holder
|
|
152
|
+
(e.g. `agent-$$` or a UUID) so two local agents sharing one `git user.name` don't
|
|
153
|
+
both think they hold the slot. The **claim/resume actor must stay stable** per
|
|
154
|
+
worktree/session — resolve `BEADS_ACTOR` → `git user.name` → `$USER` (never
|
|
155
|
+
empty). Use the unique value **only** for `bd merge-slot acquire/check/release`;
|
|
156
|
+
keep the stable `BEADS_ACTOR` for the resume lookup and `bd ready --claim`.
|
|
157
|
+
|
|
158
|
+
1. **Resume the actor's own in-flight *plan* task first.** Before claiming
|
|
159
|
+
anything new — and using the **stable** claim actor, not the per-process lock
|
|
160
|
+
identity — check for a **plan-derived** task already `in_progress` assigned to
|
|
161
|
+
you, scoped exactly like claiming:
|
|
162
|
+
`bd list --status in_progress --assignee <actor> --has-metadata-key plan_task_id --json`.
|
|
163
|
+
If one exists, continue it (see "Resume In-Progress Work" below). Scoping to
|
|
164
|
+
`plan_task_id` prevents resuming onto an unrelated manual/bootstrap issue
|
|
165
|
+
assigned to the same actor; any such non-plan in-progress work is reported
|
|
166
|
+
separately, not resumed as build work.
|
|
167
|
+
2. **Reconcile merged PRs.** If a PR shows as merged, close the corresponding
|
|
168
|
+
task: `bd close <id>`.
|
|
169
|
+
3. **Orchestrator-only materialization under the merge-slot lock.** Only the wave
|
|
170
|
+
orchestrator (the first agent resuming the wave) runs the materializer;
|
|
171
|
+
workers skip to step 4. The orchestrator:
|
|
172
|
+
- **Clears/overwrites any stale completion signal before acquiring the lock**,
|
|
173
|
+
so a signal left from a previous pipeline run (or a pre-update plan) can't
|
|
174
|
+
let workers race ahead of a fresh re-materialization. The **completion
|
|
175
|
+
signal must be run-stamped** — carry a `run_id` or the current plan hash
|
|
176
|
+
(e.g. a metadata flag on the project merge-slot/bootstrap bead, or a
|
|
177
|
+
workspace marker recording `run_id` / `materialized_at`).
|
|
178
|
+
- **Acquires the lock with a real acquisition loop, not a status poll** — loop
|
|
179
|
+
on `bd merge-slot acquire` itself and re-verify ownership via
|
|
180
|
+
`bd merge-slot check --json` (a released slot is `holder: null` and never
|
|
181
|
+
auto-promotes a waiter). Guard the non-zero/queued return with `|| true` and
|
|
182
|
+
release via a `trap … EXIT INT TERM`.
|
|
183
|
+
- **Once ownership is confirmed, invokes `/scaffold:materialize-plan-to-beads`**
|
|
184
|
+
(the canonical procedure — do not duplicate the four-pass logic). It is
|
|
185
|
+
idempotent and a cheap no-op when in sync. If it returns non-zero, **fail
|
|
186
|
+
closed** (do not set the signal, do not claim, do not markdown-fall-back).
|
|
187
|
+
- On success, **sets the run-stamped completion signal**, then **releases**
|
|
188
|
+
the slot.
|
|
189
|
+
4. **Workers block on the run-stamped completion signal before their first
|
|
190
|
+
claim.** A released slot (`holder: null`) does **not** prove the orchestrator
|
|
191
|
+
ran — blocking on slot release alone is insufficient (a worker could
|
|
192
|
+
acquire/release before the orchestrator started). Workers wait until a signal
|
|
193
|
+
matching **this run's** `run_id`/plan-hash is present, then proceed.
|
|
194
|
+
5. **Clean up and run the scoped claim loop** (using the **stable** `BEADS_ACTOR`,
|
|
195
|
+
not the per-process lock identity):
|
|
196
|
+
- `git fetch origin --prune && git clean -fd`
|
|
197
|
+
- Run the install command from CLAUDE.md Key Commands
|
|
198
|
+
- Atomically claim the next ready **plan** task:
|
|
199
|
+
`TASK=$(bd ready --claim --has-metadata-key plan_task_id --json | jq -r '.id')`
|
|
200
|
+
- Scoping to `plan_task_id` keeps the loop from ever claiming the bootstrap
|
|
201
|
+
"initialize Beads" bead or a manually-created issue.
|
|
202
|
+
- This sets `assignee=$BEADS_ACTOR` + `status=in_progress` in a single
|
|
203
|
+
round-trip — no race window between agents.
|
|
204
|
+
6. Continue until the scoped claim
|
|
205
|
+
(`bd ready --claim --has-metadata-key plan_task_id --json`) returns no ready
|
|
206
|
+
task, then run the **completion check**.
|
|
207
|
+
|
|
208
|
+
**Completion check (empty `bd ready` ≠ done).** An empty scoped-ready result does
|
|
209
|
+
**not** mean the build is finished. On an empty result, fetch all plan-derived
|
|
210
|
+
tasks (`bd list --all --limit 0 --has-metadata-key plan_task_id --json`) and
|
|
211
|
+
classify the remaining non-`closed` tasks:
|
|
212
|
+
|
|
213
|
+
- **All plan tasks `closed`** → genuinely **done**; exit gracefully.
|
|
214
|
+
- Otherwise classify **each** remaining non-`closed` task independently — do
|
|
215
|
+
**not** short-circuit on "any task is `in_progress`". Resolve blocker statuses
|
|
216
|
+
from an **unfiltered** `bd list --all --limit 0 --json` (manual blockers carry
|
|
217
|
+
no `plan_task_id`):
|
|
218
|
+
- **advancing** — the task is itself `in_progress`, **or** a **transitive**
|
|
219
|
+
blocker (walk the chain; bound the walk, reuse `bd dep cycles`) is
|
|
220
|
+
`in_progress`.
|
|
221
|
+
- **stalled** — not `in_progress` and no transitive blocker is `in_progress`.
|
|
222
|
+
- **All remaining advancing** → exit gracefully (normal multi-agent case). **Any
|
|
223
|
+
stalled** → **stop and report the stalled subset**, grouped by why (open
|
|
224
|
+
dependency, manual `blocked`, `deferred`). Unrelated global `in_progress` work
|
|
225
|
+
that blocks none of the stalled tasks does **not** suppress the report.
|
|
226
|
+
|
|
227
|
+
**Markdown fallback** (only when `.beads/` is **absent**, or for a genuinely
|
|
228
|
+
legacy plan per the table — never past existing Beads state):
|
|
133
229
|
- Read `docs/implementation-playbook.md` as the primary task reference.
|
|
134
230
|
Fall back to `docs/implementation-plan.md` when no playbook is present.
|
|
135
231
|
- If a PR shows as merged, mark the corresponding task as complete in the plan/playbook
|
|
@@ -123,17 +123,110 @@ These rules are critical for multi-agent operation:
|
|
|
123
123
|
|
|
124
124
|
### Beads Detection
|
|
125
125
|
|
|
126
|
-
|
|
127
|
-
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
126
|
+
The implementation plan is materialized into Beads issues by
|
|
127
|
+
`/scaffold:materialize-plan-to-beads` before the build phase. This block is the
|
|
128
|
+
**defensive preflight** that guarantees the tracker is populated and current
|
|
129
|
+
before any agent claims work — it never claims against an empty or stale tracker.
|
|
130
|
+
Under multi-agent concurrency, materialization is **orchestrator-only** and runs
|
|
131
|
+
**once per wave under a merge-slot lock**; workers never materialize and must
|
|
132
|
+
wait for a run-stamped completion signal before their first claim.
|
|
133
|
+
|
|
134
|
+
**Step 1 — compute `beads_usable`.** `beads_usable` is true only when **all**
|
|
135
|
+
hold: `.beads/` exists, `bd` is on `PATH`, `bd version` parses to **≥ 1.0.5**
|
|
136
|
+
(using a macOS/BSD-safe numeric compare — split major/minor/patch and compare
|
|
137
|
+
numerically, never rely on GNU `sort -V`), and `jq` is on `PATH`. Never write
|
|
138
|
+
`[ -d .beads ] && bd …` as a whole command — it returns exit 1 when `.beads/` is
|
|
139
|
+
absent and breaks callers under `set -e`; use an `if`.
|
|
140
|
+
|
|
141
|
+
**Step 2 — route on the decision table** (this is what prevents the "empty
|
|
142
|
+
tracker looks done" bug):
|
|
143
|
+
|
|
144
|
+
| Condition | Action |
|
|
145
|
+
|---|---|
|
|
146
|
+
| `.beads/` **absent** | Non-Beads project → drive the loop from the markdown playbook/plan (see "Markdown fallback" below). Do **not** call `bd`. |
|
|
147
|
+
| `.beads/` present but `beads_usable` is false (`bd`/`jq` missing or `bd` < 1.0.5) | **Fail closed.** Stop and tell the user to install/upgrade `bd` (≥ v1.0.5) and `jq`. Do **not** markdown-fall-back — Beads may already hold execution state. |
|
|
148
|
+
| `beads_usable`, but the plan has **no** stable task IDs **and** Beads holds no plan-derived issues and no non-bootstrap claimed/closed work | Genuinely legacy plan → markdown loop, and emit "re-run planning to assign stable task IDs". Do **not** claim. |
|
|
149
|
+
| `beads_usable`, plan has no stable IDs **but** Beads already holds plausible build work (claimed/closed non-bootstrap issues) | **Fail closed** — markdown would bypass existing execution state. Require re-running planning + materialization. |
|
|
150
|
+
| `beads_usable`, contract **partially present or malformed** | **Fail closed.** Do **not** markdown-fall-back (would bypass existing plan-derived issues and diverge). Require planning to be re-run/fixed. |
|
|
151
|
+
| `beads_usable` **and a valid stable-ID contract** | **Orchestrator materializes once under the lock, then everyone claims** (see Step 3). |
|
|
152
|
+
|
|
153
|
+
**Step 3 — `beads_usable` + valid contract → orchestrator materializes, workers wait, then claim:**
|
|
154
|
+
|
|
155
|
+
Branch naming: `bd-<id>/<desc>`. Verify `$BEADS_ACTOR` is set per agent (echo it;
|
|
156
|
+
bail if empty).
|
|
157
|
+
|
|
158
|
+
**Two distinct identities.** The merge-slot needs a **per-process unique** holder
|
|
159
|
+
(e.g. `agent-$$` or a UUID) so two local agents sharing one `git user.name` don't
|
|
160
|
+
both think they hold the slot. The **claim/resume actor must stay stable** per
|
|
161
|
+
worktree/session — resolve `BEADS_ACTOR` → `git user.name` → `$USER` (never
|
|
162
|
+
empty). Use the unique value **only** for `bd merge-slot acquire/check/release`;
|
|
163
|
+
keep the stable `BEADS_ACTOR` for `bd ready --claim`. If you must override
|
|
164
|
+
`BEADS_ACTOR` for the lock, scope that override to the lock commands and restore
|
|
165
|
+
the stable actor before claiming.
|
|
166
|
+
|
|
167
|
+
1. **Orchestrator-only materialization under the merge-slot lock.** Only the wave
|
|
168
|
+
orchestrator (the first agent) runs the materializer; workers skip to step 2.
|
|
169
|
+
The orchestrator:
|
|
170
|
+
- **Clears/overwrites any stale completion signal before acquiring the lock**,
|
|
171
|
+
so a signal left from a previous pipeline run (or a pre-update plan) can't
|
|
172
|
+
let workers race ahead of a fresh re-materialization. The **completion
|
|
173
|
+
signal must be run-stamped** — carry a `run_id` or the current plan hash
|
|
174
|
+
(e.g. a metadata flag on the project merge-slot/bootstrap bead, or a
|
|
175
|
+
workspace marker file recording `run_id` / `materialized_at`).
|
|
176
|
+
- **Acquires the lock with a real acquisition loop, not a status poll** — loop
|
|
177
|
+
on `bd merge-slot acquire` itself and re-verify ownership via
|
|
178
|
+
`bd merge-slot check --json` (a released slot is `holder: null` and never
|
|
179
|
+
auto-promotes a waiter, so a check-only loop deadlocks). Guard the
|
|
180
|
+
non-zero/queued return with `|| true` and release via a
|
|
181
|
+
`trap … EXIT INT TERM`.
|
|
182
|
+
- **Once ownership is confirmed, invokes `/scaffold:materialize-plan-to-beads`**
|
|
183
|
+
(the canonical procedure — do not duplicate the four-pass logic). It is
|
|
184
|
+
idempotent and a cheap no-op when already in sync. If it returns non-zero,
|
|
185
|
+
**fail closed** (do not set the signal, do not claim, do not markdown-fall-back).
|
|
186
|
+
- On success, **sets the run-stamped completion signal**, then **releases**
|
|
187
|
+
the slot.
|
|
188
|
+
2. **Workers block on the run-stamped completion signal before their first
|
|
189
|
+
claim.** A released slot (`holder: null`) does **not** prove the orchestrator
|
|
190
|
+
ran — a worker could acquire/release before the orchestrator even started. So
|
|
191
|
+
workers wait until a signal matching **this run's** `run_id`/plan-hash is
|
|
192
|
+
present, then proceed. The lock serializes the *write*; the run-stamped signal
|
|
193
|
+
gates the *readers*.
|
|
194
|
+
3. **Run the scoped claim loop** (using the **stable** `BEADS_ACTOR`, not the
|
|
195
|
+
per-process lock identity). Atomically claim the next ready **plan** task:
|
|
196
|
+
`TASK=$(bd ready --claim --has-metadata-key plan_task_id --json | jq -r '.id')`
|
|
197
|
+
- Scoping to `plan_task_id` keeps the loop from ever claiming the bootstrap
|
|
198
|
+
"initialize Beads" bead or a manually-created issue.
|
|
199
|
+
- This sets `assignee=$BEADS_ACTOR` and `status=in_progress` in a single
|
|
200
|
+
round-trip — eliminates the race window where two agents both see the same
|
|
201
|
+
"ready" task.
|
|
202
|
+
4. Implement following the TDD workflow below.
|
|
203
|
+
5. After the PR is merged: `bd close <id>`.
|
|
204
|
+
6. Repeat the scoped claim (`bd ready --claim --has-metadata-key plan_task_id --json`)
|
|
205
|
+
until it returns no ready task, then run the **completion check**.
|
|
206
|
+
|
|
207
|
+
**Completion check (empty `bd ready` ≠ done).** An empty scoped-ready result does
|
|
208
|
+
**not** mean the build is finished. On an empty result, fetch all plan-derived
|
|
209
|
+
tasks (`bd list --all --limit 0 --has-metadata-key plan_task_id --json`) and
|
|
210
|
+
classify the remaining non-`closed` tasks:
|
|
211
|
+
|
|
212
|
+
- **All plan tasks `closed`** → genuinely **done**; exit gracefully.
|
|
213
|
+
- Otherwise classify **each** remaining non-`closed` task independently — do
|
|
214
|
+
**not** short-circuit on "any task is `in_progress`". Resolve blocker statuses
|
|
215
|
+
from an **unfiltered** `bd list --all --limit 0 --json` (manual blockers carry
|
|
216
|
+
no `plan_task_id`):
|
|
217
|
+
- **advancing** — the task is itself `in_progress`, **or** at least one of its
|
|
218
|
+
**transitive** blockers (walk the chain; bound the walk, reuse
|
|
219
|
+
`bd dep cycles`) is `in_progress`.
|
|
220
|
+
- **stalled** — not `in_progress` and **no** transitive blocker is
|
|
221
|
+
`in_progress`.
|
|
222
|
+
- **All remaining tasks advancing** → exit gracefully (normal multi-agent case;
|
|
223
|
+
other agents are still working).
|
|
224
|
+
- **Any task stalled** → **stop and report the stalled subset**, grouped by why
|
|
225
|
+
(open dependency, manual `blocked`, `deferred`). Unrelated global `in_progress`
|
|
226
|
+
work that blocks none of the stalled tasks does **not** suppress the report.
|
|
227
|
+
|
|
228
|
+
**Markdown fallback** (only when `.beads/` is **absent**, or for a genuinely
|
|
229
|
+
legacy plan per the table — never past existing Beads state):
|
|
137
230
|
- Branch naming: `<type>/<desc>` (e.g., `feat/add-auth`)
|
|
138
231
|
1. Read `docs/implementation-playbook.md` as the primary task execution reference.
|
|
139
232
|
Fall back to `docs/implementation-plan.md` when no playbook is present.
|
|
@@ -96,14 +96,80 @@ Recover your context by checking the current state of work:
|
|
|
96
96
|
|
|
97
97
|
### Beads Recovery
|
|
98
98
|
|
|
99
|
-
|
|
100
|
-
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
99
|
+
The implementation plan is materialized into Beads issues by
|
|
100
|
+
`/scaffold:materialize-plan-to-beads` before the build phase. A resumed build
|
|
101
|
+
runs the **same defensive preflight** as the start prompt — it never claims
|
|
102
|
+
against an empty or stale tracker.
|
|
103
|
+
|
|
104
|
+
**Step 1 — compute `beads_usable`.** `beads_usable` is true only when **all**
|
|
105
|
+
hold: `.beads/` exists, `bd` is on `PATH`, `bd version` parses to **≥ 1.0.5**
|
|
106
|
+
(using a macOS/BSD-safe numeric compare — split major/minor/patch and compare
|
|
107
|
+
numerically, never rely on GNU `sort -V`), and `jq` is on `PATH`. Never write
|
|
108
|
+
`[ -d .beads ] && bd …` as a whole command — it returns exit 1 when `.beads/` is
|
|
109
|
+
absent and breaks callers under `set -e`; use an `if`.
|
|
110
|
+
|
|
111
|
+
**Step 2 — route on the decision table** (this is what prevents the "empty
|
|
112
|
+
tracker looks done" bug):
|
|
113
|
+
|
|
114
|
+
| Condition | Action |
|
|
115
|
+
|---|---|
|
|
116
|
+
| `.beads/` **absent** | Non-Beads project → drive the loop from the markdown playbook/plan (see "Markdown fallback" below). Do **not** call `bd`. |
|
|
117
|
+
| `.beads/` present but `beads_usable` is false (`bd`/`jq` missing or `bd` < 1.0.5) | **Fail closed.** Stop and tell the user to install/upgrade `bd` (≥ v1.0.5) and `jq`. Do **not** markdown-fall-back — Beads may already hold execution state. |
|
|
118
|
+
| `beads_usable`, plan has **no** stable IDs **and** Beads holds no plan-derived issues and no non-bootstrap claimed/closed work | Genuinely legacy plan → markdown loop, emit "re-run planning to assign stable task IDs". Do **not** claim. |
|
|
119
|
+
| `beads_usable`, plan has no stable IDs **but** Beads already holds plausible build work | **Fail closed** — markdown would bypass existing execution state. |
|
|
120
|
+
| `beads_usable`, contract **partially present or malformed** | **Fail closed.** Do **not** markdown-fall-back. Require planning to be re-run/fixed. |
|
|
121
|
+
| `beads_usable` **and a valid stable-ID contract** | **Resume your own task, materialize, then claim** (see Step 3). |
|
|
122
|
+
|
|
123
|
+
**Step 3 — `beads_usable` + valid contract:**
|
|
124
|
+
|
|
125
|
+
1. **Resume the actor's own in-flight *plan* task first.** Before claiming
|
|
126
|
+
anything new — and using the **stable** claim actor (resolve `BEADS_ACTOR` →
|
|
127
|
+
`git user.name` → `$USER`, never empty) — check for a **plan-derived** task
|
|
128
|
+
already `in_progress` assigned to you, scoped exactly like claiming:
|
|
129
|
+
`bd list --status in_progress --assignee <actor> --has-metadata-key plan_task_id --json`.
|
|
130
|
+
If one exists, continue it (see "Resume In-Progress Work" below). Scoping to
|
|
131
|
+
`plan_task_id` prevents resuming onto an unrelated manual/bootstrap issue
|
|
132
|
+
assigned to the same actor; any such non-plan in-progress work is reported
|
|
133
|
+
separately, not resumed as build work.
|
|
134
|
+
2. **Reconcile merged PRs.** If a PR shows as merged, close the corresponding
|
|
135
|
+
task: `bd close <id>`.
|
|
136
|
+
3. **Always invoke the canonical materializer** before claiming new work:
|
|
137
|
+
`/scaffold:materialize-plan-to-beads`. Run it unconditionally — do **not**
|
|
138
|
+
gate it on a count or ID-set comparison. It is idempotent (a cheap no-op when
|
|
139
|
+
in sync) and is the single source of the four-pass reconcile logic — this
|
|
140
|
+
prompt **invokes** it, it does not duplicate it. If it returns non-zero,
|
|
141
|
+
**fail closed** — stop, surface the error, do **not** claim and do **not**
|
|
142
|
+
markdown-fall-back past existing Beads state.
|
|
143
|
+
4. **Run the scoped claim loop.** Atomically claim the next ready **plan** task:
|
|
144
|
+
`TASK=$(bd ready --claim --has-metadata-key plan_task_id --json | jq -r '.id')`
|
|
145
|
+
- Scoping to `plan_task_id` keeps the loop from ever claiming the bootstrap
|
|
146
|
+
"initialize Beads" bead or a manually-created issue.
|
|
147
|
+
- This sets `assignee=$BEADS_ACTOR` + `status=in_progress` in a single
|
|
148
|
+
round-trip — no race window.
|
|
149
|
+
5. Continue until the scoped claim
|
|
150
|
+
(`bd ready --claim --has-metadata-key plan_task_id --json`) returns no ready
|
|
151
|
+
task, then run the **completion check**.
|
|
152
|
+
|
|
153
|
+
**Completion check (empty `bd ready` ≠ done).** An empty scoped-ready result does
|
|
154
|
+
**not** mean the build is finished. On an empty result, fetch all plan-derived
|
|
155
|
+
tasks (`bd list --all --limit 0 --has-metadata-key plan_task_id --json`) and
|
|
156
|
+
classify the remaining non-`closed` tasks:
|
|
157
|
+
|
|
158
|
+
- **All plan tasks `closed`** → genuinely **done**; exit gracefully.
|
|
159
|
+
- Otherwise classify **each** remaining non-`closed` task independently — do
|
|
160
|
+
**not** short-circuit on "any task is `in_progress`". Resolve blocker statuses
|
|
161
|
+
from an **unfiltered** `bd list --all --limit 0 --json` (manual blockers carry
|
|
162
|
+
no `plan_task_id`):
|
|
163
|
+
- **advancing** — the task is itself `in_progress`, **or** a **transitive**
|
|
164
|
+
blocker (walk the chain; bound the walk, reuse `bd dep cycles`) is
|
|
165
|
+
`in_progress`.
|
|
166
|
+
- **stalled** — not `in_progress` and no transitive blocker is `in_progress`.
|
|
167
|
+
- **All remaining advancing** → exit gracefully. **Any stalled** → **stop and
|
|
168
|
+
report the stalled subset**, grouped by why (open dependency, manual `blocked`,
|
|
169
|
+
`deferred`).
|
|
170
|
+
|
|
171
|
+
**Markdown fallback** (only when `.beads/` is **absent**, or for a genuinely
|
|
172
|
+
legacy plan per the table — never past existing Beads state):
|
|
107
173
|
- Read `docs/implementation-playbook.md` as the primary task reference.
|
|
108
174
|
Fall back to `docs/implementation-plan.md` when no playbook is present.
|
|
109
175
|
- If a PR shows as merged, mark the corresponding task as complete in the plan/playbook
|