bmad-plus 0.21.0 → 0.23.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 +39 -0
- package/README.md +24 -14
- package/SECURITY.md +63 -1
- package/osint-agent-package/skills/bmad-osint-investigate/osint/scripts/_http.py +68 -24
- package/package.json +4 -1
- package/readme-international/README.de.md +24 -14
- package/readme-international/README.es.md +24 -14
- package/readme-international/README.fr.md +24 -14
- package/src/bmad-plus/agents/agent-orchestrator/SKILL.md +5 -1
- package/src/bmad-plus/data/role-triggers.yaml +34 -0
- package/src/bmad-plus/module-help.csv +2 -0
- package/src/bmad-plus/module.yaml +21 -0
- package/src/bmad-plus/packs/pack-design/SKILL.md +72 -0
- package/src/bmad-plus/packs/pack-design/bmad-skill-manifest.yaml +13 -0
- package/src/bmad-plus/packs/pack-design/design-engine.md +126 -0
- package/src/bmad-plus/packs/pack-design/intake.yaml +105 -0
- package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/code-review.md +3 -1
- package/src/bmad-plus/packs/pack-seo/SKILL.md +3 -1
- package/src/bmad-plus/packs/pack-seo/ref/cwv-thresholds.md +2 -2
- package/src/bmad-plus/packs/pack-seo/requirements.txt +1 -1
- package/src/bmad-plus/packs/pack-seo/scripts/seo_apis.py +72 -30
- package/src/bmad-plus/packs/pack-seo/scripts/seo_report.py +5 -6
- package/src/bmad-plus/packs/pack-seo/scripts/seo_screenshot.py +176 -14
- package/src/bmad-plus/packs/pack-shield/README.md +12 -0
- package/src/bmad-plus/packs/pack-shield/SKILL.md +7 -1
- package/src/bmad-plus/packs/pack-shield/review-rules/access-control.md +10 -0
- package/src/bmad-plus/packs/pack-shield/review-rules/ai-integrations.md +10 -0
- package/src/bmad-plus/packs/pack-shield/review-rules/change-and-supply-chain.md +10 -0
- package/src/bmad-plus/packs/pack-shield/review-rules/cryptography.md +10 -0
- package/src/bmad-plus/packs/pack-shield/review-rules/index.yaml +134 -0
- package/src/bmad-plus/packs/pack-shield/review-rules/logging.md +10 -0
- package/src/bmad-plus/packs/pack-shield/review-rules/personal-data.md +10 -0
- package/src/bmad-plus/packs/pack-shield/shared/ai-processing-register-template.yaml +53 -0
- package/src/bmad-plus/packs/pack-shield/shared/ai-processing-register.md +32 -0
- package/src/bmad-plus/packs/pack-shield/shared/assurance-case-template.yaml +87 -0
- package/src/bmad-plus/packs/pack-shield/shared/assurance-case.md +50 -0
- package/src/bmad-plus/packs/pack-shield/shield-orchestrator.md +24 -1
- package/src/bmad-plus/skills/bmad-plus-autopilot/SKILL.md +7 -0
- package/src/bmad-plus/skills/bmad-plus-intake/SKILL.md +87 -0
- package/src/bmad-plus/skills/bmad-plus-intake/ref/intake-format.md +112 -0
- package/src/bmad-plus/skills/bmad-plus-parallel/SKILL.md +18 -0
- package/src/bmad-plus/skills/bmad-plus-swarm/SKILL.md +115 -0
- package/src/bmad-plus/skills/bmad-plus-swarm/ref/definition.md +188 -0
- package/src/bmad-plus/skills/bmad-plus-uat/SKILL.md +1 -0
- package/src/bmad-plus/skills/bmad-plus-uat/template/page.html +5 -4
- package/tools/build/adapters.config.js +2 -0
- package/tools/build/generate-adapters.js +32 -1
- package/tools/build/generate.js +283 -7
- package/tools/build/intake-contract.js +522 -0
- package/tools/cli/bmad-plus-cli.js +4 -0
- package/tools/cli/commands/ai-register.js +63 -0
- package/tools/cli/commands/assurance.js +162 -0
- package/tools/cli/commands/install.js +28 -1
- package/tools/cli/commands/intake.js +124 -0
- package/tools/cli/commands/review.js +10 -3
- package/tools/cli/commands/swarm.js +119 -0
- package/tools/cli/commands/uninstall.js +17 -0
- package/tools/cli/i18n.js +20 -0
- package/tools/cli/lib/ai-register.js +393 -0
- package/tools/cli/lib/assurance.js +822 -0
- package/tools/cli/lib/control-refs.js +132 -0
- package/tools/cli/lib/installation-health.js +17 -0
- package/tools/cli/lib/intake.js +202 -0
- package/tools/cli/lib/pack-copy.js +95 -5
- package/tools/cli/lib/packs.js +156 -8
- package/tools/cli/lib/page-origins.js +582 -0
- package/tools/cli/lib/review-rules.js +92 -24
- package/tools/cli/lib/review.js +28 -1
- package/tools/cli/lib/swarm-deal.js +116 -0
- package/tools/cli/lib/swarm-defaults.js +6 -0
- package/tools/cli/lib/swarm-tally.js +195 -0
- package/tools/cli/lib/swarm-validate.js +589 -0
- package/tools/cli/lib/swarm.js +712 -0
- package/tools/cli/lib/uat.js +22 -5
- package/tools/cli/lib/update-transaction.js +8 -4
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# Shield compliance review rules, applied by path once the Shield pack is installed.
|
|
2
|
+
# They add to the built-in rules (a pack never replaces or disables one); a project replaces
|
|
3
|
+
# or disables them by id in _bmad/review-rules.yaml. Every rule names the controls it
|
|
4
|
+
# examines as FRAMEWORK:ID (bmad-plus review rules lists them), so a checklist can say which
|
|
5
|
+
# controls a change touches. All rules share the `compliance` group: one parallel reviewer
|
|
6
|
+
# can take them together.
|
|
7
|
+
schema: bmad-plus/review-rules/1
|
|
8
|
+
rules:
|
|
9
|
+
- id: shield-access-control
|
|
10
|
+
title: Identity, authentication and authorisation
|
|
11
|
+
group: compliance
|
|
12
|
+
globs:
|
|
13
|
+
- '**/{auth,authn,authz,login,session,sessions,permissions,rbac,acl,oauth,oidc,sso,iam,guards,policies}/**'
|
|
14
|
+
- '**/*{auth,Auth,session,Session,permission,Permission,policy,Policy}*.*'
|
|
15
|
+
controls:
|
|
16
|
+
[
|
|
17
|
+
ISO27001:A.5.15,
|
|
18
|
+
ISO27001:A.5.18,
|
|
19
|
+
ISO27001:A.8.2,
|
|
20
|
+
ISO27001:A.8.5,
|
|
21
|
+
SOC2:CC6.1,
|
|
22
|
+
SOC2:CC6.2,
|
|
23
|
+
SOC2:CC6.3,
|
|
24
|
+
NIST-800-53:AC-3,
|
|
25
|
+
NIST-800-53:AC-6,
|
|
26
|
+
NIST-800-53:IA-2,
|
|
27
|
+
NIS2:Art.21(2)(i),
|
|
28
|
+
NIS2:Art.21(2)(j),
|
|
29
|
+
]
|
|
30
|
+
doc: access-control.md
|
|
31
|
+
- id: shield-personal-data
|
|
32
|
+
title: Personal data in models, schemas and migrations
|
|
33
|
+
group: compliance
|
|
34
|
+
globs:
|
|
35
|
+
- '**/{models,entities,schemas,schema,dto,dtos,migrations,migrate}/**'
|
|
36
|
+
- '**/*{user,User,customer,Customer,profile,Profile,account,Account,contact,Contact,consent,Consent,privacy,Privacy}*.*'
|
|
37
|
+
controls:
|
|
38
|
+
[
|
|
39
|
+
GDPR:Art.5(1)(c),
|
|
40
|
+
GDPR:Art.5(1)(e),
|
|
41
|
+
GDPR:Art.25,
|
|
42
|
+
GDPR:Art.30,
|
|
43
|
+
GDPR:Art.32,
|
|
44
|
+
ISO27001:A.5.34,
|
|
45
|
+
ISO27001:A.8.10,
|
|
46
|
+
ISO27001:A.8.11,
|
|
47
|
+
SOC2:P4.2,
|
|
48
|
+
SOC2:P4.3,
|
|
49
|
+
]
|
|
50
|
+
doc: personal-data.md
|
|
51
|
+
- id: shield-cryptography
|
|
52
|
+
title: Cryptography, keys and secrets handling
|
|
53
|
+
group: compliance
|
|
54
|
+
globs:
|
|
55
|
+
- '**/{crypto,cryptography,security,secrets,certs,certificates,tls,vault,kms}/**'
|
|
56
|
+
- '**/*{crypt,Crypt,cipher,Cipher,hash,Hash,signature,Signature,token,Token,secret,Secret}*.*'
|
|
57
|
+
controls:
|
|
58
|
+
[
|
|
59
|
+
ISO27001:A.8.24,
|
|
60
|
+
ISO27001:A.5.17,
|
|
61
|
+
SOC2:CC6.1,
|
|
62
|
+
SOC2:CC6.7,
|
|
63
|
+
NIST-800-53:SC-8,
|
|
64
|
+
NIST-800-53:SC-12,
|
|
65
|
+
NIST-800-53:SC-13,
|
|
66
|
+
NIST-800-53:SC-28,
|
|
67
|
+
GDPR:Art.32(1)(a),
|
|
68
|
+
NIS2:Art.21(2)(h),
|
|
69
|
+
]
|
|
70
|
+
doc: cryptography.md
|
|
71
|
+
- id: shield-logging
|
|
72
|
+
title: Logging, audit trail and monitoring
|
|
73
|
+
group: compliance
|
|
74
|
+
globs:
|
|
75
|
+
- '**/{logs,logger,logging,audit,telemetry,observability,monitoring,metrics,tracing}/**'
|
|
76
|
+
- '**/*{logger,Logger,logging,Logging,audit,Audit,telemetry,Telemetry}*.*'
|
|
77
|
+
controls:
|
|
78
|
+
[
|
|
79
|
+
ISO27001:A.8.15,
|
|
80
|
+
ISO27001:A.8.16,
|
|
81
|
+
ISO27001:A.8.17,
|
|
82
|
+
SOC2:CC7.2,
|
|
83
|
+
SOC2:CC7.3,
|
|
84
|
+
NIST-800-53:AU-2,
|
|
85
|
+
NIST-800-53:AU-3,
|
|
86
|
+
NIST-800-53:AU-9,
|
|
87
|
+
NIST-800-53:AU-11,
|
|
88
|
+
GDPR:Art.5(1)(c),
|
|
89
|
+
NIS2:Art.23,
|
|
90
|
+
]
|
|
91
|
+
doc: logging.md
|
|
92
|
+
- id: shield-ai-integrations
|
|
93
|
+
title: AI models, prompts and agent tooling
|
|
94
|
+
group: compliance
|
|
95
|
+
globs:
|
|
96
|
+
- '**/{ai,llm,llms,prompts,agents,mcp,rag,embeddings}/**'
|
|
97
|
+
- '**/*{openai,OpenAI,anthropic,Anthropic,gemini,Gemini,llm,LLM,prompt,Prompt}*.*'
|
|
98
|
+
- '**/{.mcp.json,mcp.json}'
|
|
99
|
+
- '{CLAUDE,GEMINI,AGENTS,CONVENTIONS}.md'
|
|
100
|
+
- '{.claude,.cursor,.codex,.opencode,.gemini}/**'
|
|
101
|
+
controls:
|
|
102
|
+
[
|
|
103
|
+
GDPR:Art.28,
|
|
104
|
+
GDPR:Art.35,
|
|
105
|
+
GDPR:Art.44,
|
|
106
|
+
EU-AI-Act:Art.50,
|
|
107
|
+
ISO27001:A.5.19,
|
|
108
|
+
ISO27001:A.5.23,
|
|
109
|
+
ISO27001:A.8.12,
|
|
110
|
+
]
|
|
111
|
+
doc: ai-integrations.md
|
|
112
|
+
- id: shield-change-and-supply-chain
|
|
113
|
+
title: Change control and supply chain
|
|
114
|
+
group: compliance
|
|
115
|
+
globs:
|
|
116
|
+
- '.github/workflows/**/*.{yml,yaml}'
|
|
117
|
+
- '**/{.gitlab-ci.yml,azure-pipelines.yml,bitbucket-pipelines.yml,CODEOWNERS}'
|
|
118
|
+
- '**/{package.json,pyproject.toml,requirements*.txt,go.mod,Cargo.toml,composer.json,Gemfile}'
|
|
119
|
+
- '**/{Dockerfile,Containerfile}'
|
|
120
|
+
controls:
|
|
121
|
+
[
|
|
122
|
+
ISO27001:A.8.25,
|
|
123
|
+
ISO27001:A.8.32,
|
|
124
|
+
ISO27001:A.5.21,
|
|
125
|
+
ISO27001:A.8.9,
|
|
126
|
+
SOC2:CC8.1,
|
|
127
|
+
SOC2:CC7.1,
|
|
128
|
+
NIST-800-53:CM-3,
|
|
129
|
+
NIST-800-53:SA-10,
|
|
130
|
+
NIST-800-53:SR-3,
|
|
131
|
+
NIS2:Art.21(2)(d),
|
|
132
|
+
NIS2:Art.21(2)(e),
|
|
133
|
+
]
|
|
134
|
+
doc: change-and-supply-chain.md
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
A log is evidence for an investigation and a store of personal data at the same time.
|
|
2
|
+
|
|
3
|
+
- **Security events.** Sign-in success and failure, access denied, privilege and role changes, exports, deletions and configuration changes are logged with who, what, when and from where. A security-relevant path the change adds without an event is a gap.
|
|
4
|
+
- **Content.** No passwords, tokens, keys, full card numbers, session ids or request bodies with personal data in log lines, traces, metrics labels or error reports. Identifiers are pseudonymised where the investigation does not need them in clear.
|
|
5
|
+
- **Integrity.** Audit records cannot be edited or deleted by the application account that writes them; a change that routes audit events through a mutable table or a best-effort queue that drops on failure weakens the trail.
|
|
6
|
+
- **Time.** Timestamps are in UTC from a synchronised clock and carry their zone; ordering never depends on a client-supplied time.
|
|
7
|
+
- **Retention.** The retention of new logs is set, matches the policy for their content, and is shorter for logs holding personal data than for pure security events where the policy says so.
|
|
8
|
+
- **Detection.** An alert or dashboard that the change removes, renames or silences is called out: incident detection and notification deadlines depend on it.
|
|
9
|
+
|
|
10
|
+
Name the control a finding breaks (for example `ISO27001:A.8.15` for logging) in the finding's description.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
Follow each personal field from where it enters to where it is deleted.
|
|
2
|
+
|
|
3
|
+
- **Minimisation.** A new field, column or payload property that identifies a person has a purpose the feature needs now. Collecting "in case" is the defect; so is copying a whole user object into another table, a cache, an event or a third-party call.
|
|
4
|
+
- **Special categories.** Health, biometric, political, religious, sexual orientation, criminal or children's data needs its own legal basis and safeguards; flag it even when the rest of the change is clean.
|
|
5
|
+
- **Retention and deletion.** Data added here has a retention period, and account deletion or an erasure request reaches it: backups, search indexes, analytics exports, soft-deleted rows and denormalised copies included.
|
|
6
|
+
- **Masking.** Identifiers and contact details are masked or pseudonymised where the full value is not needed: admin lists, logs, support views, test fixtures and seed data.
|
|
7
|
+
- **Migrations.** A migration that copies, backfills or widens personal data states why; a rollback does not resurrect erased data; a new nullable column that will hold personal data has a default that collects nothing.
|
|
8
|
+
- **Records of processing.** A new purpose, recipient or category of data subject is a change to the record of processing activities; say so in the finding so the register is updated.
|
|
9
|
+
|
|
10
|
+
Name the control a finding breaks (for example `GDPR:Art.5(1)(c)` for minimisation) in the finding's description.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# AI processing register (bmad-plus/ai-processing-register/1).
|
|
2
|
+
#
|
|
3
|
+
# Start with `bmad-plus ai-register init` (it writes _bmad/ai-processing-register.yaml)
|
|
4
|
+
# and describe every AI tool the project uses:
|
|
5
|
+
# coding assistants, agent CLIs, model APIs called by the product, MCP servers. Then:
|
|
6
|
+
# bmad-plus ai-register check
|
|
7
|
+
# warns about any AI integration found in the project (adapter files such as CLAUDE.md,
|
|
8
|
+
# tool folders such as .cursor/, servers declared in .mcp.json) that no entry covers.
|
|
9
|
+
# `bmad-plus doctor` reports the same when the Shield pack is installed. A missing entry
|
|
10
|
+
# never fails a build: the register is a record of processing, kept honest by review.
|
|
11
|
+
#
|
|
12
|
+
# integrations: the ids this entry covers. Tool ids are those of the BMAD+ adapters
|
|
13
|
+
# (claude-code, gemini-cli, antigravity, cursor, codex-cli, opencode, aider) or of other
|
|
14
|
+
# tools (github-copilot, windsurf, continue); an MCP server is mcp:<name as declared>.
|
|
15
|
+
# legalBasis (GDPR Art. 6(1)), only when personalData is true: consent, contract,
|
|
16
|
+
# legal-obligation, vital-interests, public-task, legitimate-interests.
|
|
17
|
+
# transfers: every destination outside the EEA with its mechanism: adequacy-decision,
|
|
18
|
+
# standard-contractual-clauses, binding-corporate-rules, derogation. [] when none.
|
|
19
|
+
# Every value below is an example: replace it with what the provider's terms actually say.
|
|
20
|
+
schema: bmad-plus/ai-processing-register/1
|
|
21
|
+
controller: Example Ltd, 1 Example Street, Example City
|
|
22
|
+
reviewed: 2026-09-29
|
|
23
|
+
|
|
24
|
+
tools:
|
|
25
|
+
- id: coding-assistant
|
|
26
|
+
name: Claude Code
|
|
27
|
+
provider: Anthropic PBC
|
|
28
|
+
integrations: [claude-code]
|
|
29
|
+
purpose: Assist developers in reading, writing and reviewing the code of this repository.
|
|
30
|
+
data:
|
|
31
|
+
- Source code and commit history of this repository
|
|
32
|
+
- File contents and command output the developer shares in a session
|
|
33
|
+
personalData: true
|
|
34
|
+
legalBasis: legitimate-interests
|
|
35
|
+
retention: The period set by the provider's terms for the plan in use, written here in days.
|
|
36
|
+
transfers:
|
|
37
|
+
- to: United States
|
|
38
|
+
mechanism: standard-contractual-clauses
|
|
39
|
+
agreement: Data processing addendum attached to the commercial terms.
|
|
40
|
+
|
|
41
|
+
- id: issue-tracker-connector
|
|
42
|
+
name: GitHub MCP server
|
|
43
|
+
provider: GitHub, Inc.
|
|
44
|
+
integrations: ['mcp:github']
|
|
45
|
+
purpose: Let the coding assistant read and comment on issues and pull requests.
|
|
46
|
+
data:
|
|
47
|
+
- Issue and pull-request text, including contributor names and handles
|
|
48
|
+
personalData: true
|
|
49
|
+
legalBasis: legitimate-interests
|
|
50
|
+
retention: Not stored by the connector; the assistant's retention applies to what it reads.
|
|
51
|
+
transfers:
|
|
52
|
+
- to: United States
|
|
53
|
+
mechanism: standard-contractual-clauses
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# AI Processing Register
|
|
2
|
+
|
|
3
|
+
> Procedure used by Shield when a user asks which AI tools touch the project's data, prepares a record of processing (GDPR Art. 30), a DPIA involving AI tooling, or an ISO 27001 / ISO 42001 supplier review. Template: `shared/ai-processing-register-template.yaml`. Tooling: `bmad-plus ai-register init|check`, and `bmad-plus doctor` when Shield is installed.
|
|
4
|
+
|
|
5
|
+
## What it produces
|
|
6
|
+
|
|
7
|
+
`_bmad/ai-processing-register.yaml`: one entry per AI tool the project uses — coding assistants, agent CLIs, model APIs called by the product, MCP servers — with its provider, purpose, the categories of data it sees, whether that includes personal data and on which legal basis, retention, transfers outside the EEA with their mechanism, and the processing agreement in place.
|
|
8
|
+
|
|
9
|
+
## Steps
|
|
10
|
+
|
|
11
|
+
1. **Inventory.** Run `bmad-plus ai-register check`. It lists the AI integrations present in the project: the adapter files BMAD+ installs (`CLAUDE.md`, `GEMINI.md`, `.cursor/rules/`, `.codex/AGENTS.md`...), the tools' own folders (`.claude/`, `.cursor/`, `.gemini/`...), and the MCP servers declared in `.mcp.json`, `.cursor/mcp.json`, `.gemini/settings.json` or `.vscode/mcp.json` (comments and trailing commas allowed). Ask the user for tools used without a trace in the repository (a model API called by the product, a browser assistant).
|
|
12
|
+
2. **One entry per tool.** `bmad-plus ai-register init` starts the file from the template; replace its example entries. An MCP server is registered as `mcp:` followed by its name exactly as declared. Fill each field from facts: the provider's terms and data processing addendum, the tool's settings (training opt-out, retention, region), what the tool can actually read. When a fact is unknown, say so to the user; do not guess a retention period or a transfer mechanism.
|
|
13
|
+
3. **Personal data.** Code rarely is, but commit authors, issue text, customer data in fixtures, logs and support tickets are. When `personalData` is true, choose the legal basis with the user (the `gdpr-agent` and `legitimate-interest` workflow help) and flag the entry for a DPIA (`dpia-sentinel`) when the processing is large-scale or novel.
|
|
14
|
+
4. **Transfers.** Every destination outside the EEA needs a mechanism; an adequacy decision covers a US provider only while it is certified under the Data Privacy Framework.
|
|
15
|
+
5. **Check again.** `bmad-plus ai-register check` must report every integration registered. Set `reviewed` to the date of the review; the check warns after twelve months.
|
|
16
|
+
|
|
17
|
+
## How the gate behaves
|
|
18
|
+
|
|
19
|
+
| Situation | Result |
|
|
20
|
+
| --------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- |
|
|
21
|
+
| An AI integration found in the project that no entry covers | Warning (exit code 0) |
|
|
22
|
+
| No register while AI integrations are present | Warning |
|
|
23
|
+
| Register last reviewed more than 365 days ago | Warning |
|
|
24
|
+
| An entry that matches nothing found here | Listed as not found; it may be used outside the repository |
|
|
25
|
+
| A register that does not follow the schema (unknown key, legal basis missing for personal data, unknown transfer mechanism) | Error (exit code 1) |
|
|
26
|
+
|
|
27
|
+
The gate is deliberately soft: it keeps the register in step with the tooling, and a missing entry never blocks a build; only a register that cannot be read exits non-zero. `bmad-plus doctor` shows every case, that one included, as a warning.
|
|
28
|
+
|
|
29
|
+
## Boundaries
|
|
30
|
+
|
|
31
|
+
- The register records processing; it does not make it lawful. The legal basis, transfer mechanism and agreements are decisions for the controller and its DPO.
|
|
32
|
+
- Detection sees configuration in the repository only. A tool installed on a developer's machine without project configuration is found by asking, not by the check.
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Security assurance case (bmad-plus/assurance-case/1).
|
|
2
|
+
#
|
|
3
|
+
# Start with `bmad-plus assurance init _bmad/assurance/<id>.yaml`, then replace every
|
|
4
|
+
# example with the project's own claims and checks. At the commit the case is about:
|
|
5
|
+
# bmad-plus assurance run _bmad/assurance/<id>.yaml
|
|
6
|
+
# bmad-plus assurance verify _bmad/assurance/<id>.yaml --ledger-head <head reported by run>
|
|
7
|
+
# --emit-check _bmad-output/assurance/<id>/check.json
|
|
8
|
+
# Keep the head outside the ledger, and set BMAD_PLUS_ASSURANCE_KEY from a secret in CI:
|
|
9
|
+
# without them the ledger shows accidental edits, not deliberate ones.
|
|
10
|
+
#
|
|
11
|
+
# Evidence is only ever a check below that ran: its command, exit code, output digest and
|
|
12
|
+
# artifact digests are recorded in a hash-chained ledger (_bmad-output/assurance/<id>/runs.jsonl).
|
|
13
|
+
# A statement, a document or a link is not evidence, and verify refuses a case that relies
|
|
14
|
+
# on one. Evidence goes stale when the commit, the command or an artifact changes, or when
|
|
15
|
+
# it is older than freshness.maxAgeDays.
|
|
16
|
+
#
|
|
17
|
+
# Commands run without a shell: write each argument separately. On Windows, programs such
|
|
18
|
+
# as npm are .cmd files and need [cmd, /c, npm, ...]. A check inherits only PATH, HOME and
|
|
19
|
+
# the temporary folders; name any other variable it needs under env.
|
|
20
|
+
schema: bmad-plus/assurance-case/1
|
|
21
|
+
id: release-security
|
|
22
|
+
title: Release security case
|
|
23
|
+
scope: >-
|
|
24
|
+
The service at the commit being released, built by the pipeline from this repository.
|
|
25
|
+
freshness:
|
|
26
|
+
maxAgeDays: 30
|
|
27
|
+
sameCommit: true
|
|
28
|
+
|
|
29
|
+
checks:
|
|
30
|
+
- id: unit-tests
|
|
31
|
+
run: [npm, test]
|
|
32
|
+
timeoutSeconds: 900
|
|
33
|
+
- id: dependency-audit
|
|
34
|
+
run: [npm, audit, --audit-level=high, --omit=dev]
|
|
35
|
+
- id: secret-scan
|
|
36
|
+
run: [gitleaks, detect, --no-banner, --redact, --report-path, reports/gitleaks.json]
|
|
37
|
+
artifacts: [reports/gitleaks.json]
|
|
38
|
+
- id: review-gate
|
|
39
|
+
run: [npx, bmad-plus, review, gate, release, --emit-check, reports/review-check.json]
|
|
40
|
+
artifacts: [reports/review-check.json]
|
|
41
|
+
|
|
42
|
+
claims:
|
|
43
|
+
- id: C1
|
|
44
|
+
claim: The release ships no known exploitable weakness, no committed credential, and no unreviewed change.
|
|
45
|
+
argument: >-
|
|
46
|
+
The top claim holds when each of the four sub-claims below holds; together they cover
|
|
47
|
+
third-party code, secrets, the change process and the behaviour the controls rely on.
|
|
48
|
+
- id: C1.1
|
|
49
|
+
parent: C1
|
|
50
|
+
claim: Production dependencies carry no known vulnerability rated high or critical.
|
|
51
|
+
argument: >-
|
|
52
|
+
npm audit compares the resolved dependency tree with the advisory database and exits
|
|
53
|
+
non-zero at the chosen level; a zero exit at this commit shows none is known today.
|
|
54
|
+
controls: [ISO27001:A.8.8, NIST-800-53:RA-5]
|
|
55
|
+
evidence:
|
|
56
|
+
- check: dependency-audit
|
|
57
|
+
shows: npm audit reports no advisory at high or above for production dependencies.
|
|
58
|
+
- id: C1.2
|
|
59
|
+
parent: C1
|
|
60
|
+
claim: No credential is committed in the repository history.
|
|
61
|
+
argument: >-
|
|
62
|
+
The scanner reads every commit reachable from this one and exits non-zero on a finding;
|
|
63
|
+
its report is kept as an artifact so the result can be inspected.
|
|
64
|
+
controls: [ISO27001:A.5.17, SOC2:CC6.1]
|
|
65
|
+
evidence:
|
|
66
|
+
- check: secret-scan
|
|
67
|
+
shows: gitleaks finds no secret in the history and writes its report.
|
|
68
|
+
- id: C1.3
|
|
69
|
+
parent: C1
|
|
70
|
+
claim: Every changed file of the release was reviewed and no finding is left open.
|
|
71
|
+
argument: >-
|
|
72
|
+
The review gate derives its verdict from coverage of the sealed scope: it exits zero
|
|
73
|
+
only when every selected file is completed or waived and no finding is open.
|
|
74
|
+
controls: [ISO27001:A.8.32, SOC2:CC8.1]
|
|
75
|
+
evidence:
|
|
76
|
+
- check: review-gate
|
|
77
|
+
shows: bmad-plus review gate reports the release review clean.
|
|
78
|
+
- id: C1.4
|
|
79
|
+
parent: C1
|
|
80
|
+
claim: The behaviour the security controls rely on is covered by passing tests.
|
|
81
|
+
argument: >-
|
|
82
|
+
Access checks, input validation and redaction have tests in the suite; the suite
|
|
83
|
+
passing at this commit shows that behaviour is intact.
|
|
84
|
+
controls: [ISO27001:A.8.29]
|
|
85
|
+
evidence:
|
|
86
|
+
- check: unit-tests
|
|
87
|
+
shows: The test suite passes at this commit.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Security Assurance Case
|
|
2
|
+
|
|
3
|
+
> Procedure used by Shield when a user asks for an assurance case, evidence for an audit, or proof that security controls hold at a given commit. Template: `shared/assurance-case-template.yaml`. Tooling: `bmad-plus assurance init|run|verify`.
|
|
4
|
+
|
|
5
|
+
## What it produces
|
|
6
|
+
|
|
7
|
+
A case in `_bmad/assurance/<id>.yaml` that states **claims**, gives for each an **argument**, and supports it with **evidence**. Evidence is only ever a check that ran: `bmad-plus assurance run` executes each declared command without a shell and appends to a hash-chained ledger what happened (exit code, output digest, digests of the artifacts the run wrote, commit, whether the tree was clean of changes and untracked files). `bmad-plus assurance verify` then refuses any claim whose evidence is missing, failed or stale, and the case file itself cannot name evidence that is only asserted.
|
|
8
|
+
|
|
9
|
+
## Steps
|
|
10
|
+
|
|
11
|
+
0. **Start.** `bmad-plus assurance init _bmad/assurance/<id>.yaml` copies this template under that id; it never overwrites a case.
|
|
12
|
+
1. **Scope.** Agree with the user on what the case covers (system, commit or release, deployment) and which frameworks matter. Write it in `scope`.
|
|
13
|
+
2. **Claims from controls.** Start from the controls in scope (the relevant framework agent and `shared/cross-framework-mapper.md` help). Write one top claim, then sub-claims narrow enough that a single command can show each one. Tag a claim with the controls it supports (`ISO27001:A.8.8`, `SOC2:CC8.1`, `GDPR:Art.32`); unknown or mistyped controls are refused.
|
|
14
|
+
3. **Checks.** For every leaf claim, choose a command that exits zero only when the claim holds: a test suite, a dependency audit, a secret scanner, a configuration linter, `bmad-plus review gate`, a policy-as-code evaluation. Declare artifacts the command writes (reports, SBOMs) so they are hashed with the run.
|
|
15
|
+
4. **Argument.** Say why a passing check shows the claim, and what it does not show. A check that cannot fail for the reason the claim is about is not evidence of it.
|
|
16
|
+
5. **Run and verify** at the commit the case is about, with a clean working tree (untracked files count unless git ignores them; the case's own ledger folder and artifacts do not):
|
|
17
|
+
```
|
|
18
|
+
bmad-plus assurance run _bmad/assurance/<id>.yaml
|
|
19
|
+
bmad-plus assurance verify _bmad/assurance/<id>.yaml --ledger-head <head> --emit-check _bmad-output/assurance/<id>/check.json
|
|
20
|
+
```
|
|
21
|
+
`run` reports the ledger head; keep it where the ledger's writers cannot change it (the CI job log, the audit file) and pass it to `verify`. In CI, run both in the same job with `BMAD_PLUS_ASSURANCE_KEY` set from a secret.
|
|
22
|
+
6. **Report.** Present the verdict: supported and unsupported claims with their reasons, and the controls that now have executed evidence (`controls.supported`). Never describe an unsupported claim as met.
|
|
23
|
+
|
|
24
|
+
## What is refused
|
|
25
|
+
|
|
26
|
+
| Situation | Result |
|
|
27
|
+
| ------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- |
|
|
28
|
+
| Evidence that is a statement, a document or a link | The case does not load: evidence must name a check |
|
|
29
|
+
| A claim with neither evidence nor sub-claims | The case does not load: the claim is only asserted |
|
|
30
|
+
| A check that never ran | `missing` — the claim is unsupported |
|
|
31
|
+
| A non-zero or unexpected exit code, a timeout, an artifact the run did not write (absent, or left unchanged from before) | `failed` |
|
|
32
|
+
| A run at another commit or on uncommitted changes or untracked files, a command changed since, an artifact changed since, a run older than `maxAgeDays` | `stale` |
|
|
33
|
+
| A ledger record edited or reordered, or removed before the last one | The whole case is unsupported until the ledger is rebuilt |
|
|
34
|
+
| The last records removed | Unsupported with `--ledger-head` given; unseen without it |
|
|
35
|
+
| A record written by hand, with its digest recomputed | Unsupported with `BMAD_PLUS_ASSURANCE_KEY` set; unseen without it |
|
|
36
|
+
|
|
37
|
+
## How far the ledger can be trusted
|
|
38
|
+
|
|
39
|
+
Without a key, the chain of SHA-256 digests shows accidental and careless edits only: anyone who can write the ledger can append a record that verifies, or cut off the records after a run they want forgotten. Two things close that, both kept outside the ledger:
|
|
40
|
+
|
|
41
|
+
- **A key.** With `BMAD_PLUS_ASSURANCE_KEY` (at least 32 characters) set, `run` signs every record with an HMAC and `verify` refuses any record the key does not authenticate. The key is never passed to a check, and a case cannot ask for it.
|
|
42
|
+
- **The head.** `verify --ledger-head <sha256>` refuses a ledger that no longer holds the record `run` reported last, so removed runs are seen.
|
|
43
|
+
|
|
44
|
+
Report which of the two applied (`ledger.authenticated`, `ledger.anchor` in the verdict); without either, say the evidence is recorded, not tamper-proof.
|
|
45
|
+
|
|
46
|
+
## Boundaries
|
|
47
|
+
|
|
48
|
+
- The case shows that named checks passed at a commit. It does not certify the system, and it is not an audit opinion: a qualified auditor decides what the evidence is worth.
|
|
49
|
+
- `assurance run` executes the commands written in the case, with the same trust as a project's own scripts. Read a case from someone else before running it.
|
|
50
|
+
- Evidence is bound to the commit by default (`freshness.sameCommit: true`). Set it to false only for a project outside git, and say so in the report.
|
|
@@ -128,6 +128,25 @@ Detect the relevant framework(s) from user input using these trigger patterns:
|
|
|
128
128
|
- FRIA, fundamental rights, Art. 27, impact assessment AI → route to `ai-act-fria`
|
|
129
129
|
- AI incident, serious incident, Art. 73, incident reporting → route to `ai-act-incidents`
|
|
130
130
|
|
|
131
|
+
**Evidence & tooling triggers:**
|
|
132
|
+
- assurance case, security case, audit evidence, prove the controls hold, claims and evidence → follow `shared/assurance-case.md`
|
|
133
|
+
- AI tools register, which AI tools see our data, record of processing for AI tooling, MCP servers inventory → follow `shared/ai-processing-register.md`
|
|
134
|
+
- compliance review of a change, which controls does this change touch → use the Shield review rules (see Evidence & Tooling below)
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Evidence & Tooling
|
|
139
|
+
|
|
140
|
+
Three Shield capabilities rest on BMAD+ CLI commands, so their results are checked by code, not asserted:
|
|
141
|
+
|
|
142
|
+
| Need | Procedure | Command |
|
|
143
|
+
|------|-----------|---------|
|
|
144
|
+
| A security assurance case whose every piece of evidence is a check that ran, at the commit concerned | `shared/assurance-case.md`, template `shared/assurance-case-template.yaml` | `bmad-plus assurance init <case>`, `bmad-plus assurance run <case>`, `bmad-plus assurance verify <case> --ledger-head <head>`; `BMAD_PLUS_ASSURANCE_KEY` authenticates the ledger |
|
|
145
|
+
| A register of the AI tools the project uses, what data they see and on which legal basis | `shared/ai-processing-register.md`, template `shared/ai-processing-register-template.yaml` | `bmad-plus ai-register init`, `bmad-plus ai-register check` (a warning, never a failure, for an unregistered tool) |
|
|
146
|
+
| A code review that says which compliance controls a change touches | `review-rules/`: access control, personal data, cryptography, logging, AI integrations, change and supply chain, all in the `compliance` group | `bmad-plus review scope` writes the checklist; `bmad-plus review rules <path>` lists the rules and controls for one file |
|
|
147
|
+
|
|
148
|
+
Controls are written `FRAMEWORK:ID` (`ISO27001:A.8.28`, `SOC2:CC8.1`, `GDPR:Art.32(1)(b)`, `NIS2:Art.21(2)(d)`, `NIST-800-53:AC-6(1)`, `EU-AI-Act:Art.50`); an unknown or mistyped control is refused. Report a supported claim or a touched control as what it is: evidence that a named check passed, or a prompt to review, never a certification. An assurance ledger without a key and a kept head shows accidental edits, not deliberate ones: say which protections applied.
|
|
149
|
+
|
|
131
150
|
---
|
|
132
151
|
|
|
133
152
|
## Multi-Framework Analysis
|
|
@@ -200,7 +219,11 @@ What type of compliance question do you have?
|
|
|
200
219
|
8. 🔄 Cross-Framework Analysis
|
|
201
220
|
"I need to comply with multiple frameworks — help me map controls."
|
|
202
221
|
|
|
203
|
-
|
|
222
|
+
9. 🧾 Evidence & AI Tooling
|
|
223
|
+
→ Assurance case, AI processing register, compliance review rules
|
|
224
|
+
"Prove our controls hold at this release" / "Which AI tools see our data?"
|
|
225
|
+
|
|
226
|
+
Which area? (1-9, or describe your situation)
|
|
204
227
|
```
|
|
205
228
|
|
|
206
229
|
---
|
|
@@ -24,9 +24,16 @@ changes use the relevant implementation/review steps directly; missing contracts
|
|
|
24
24
|
or consequential uncertainty justify deeper planning. Preserve the task's prior
|
|
25
25
|
authorization and completed artifacts when adjusting the route.
|
|
26
26
|
|
|
27
|
+
A pack that declares a pipeline in the registry replaces the generic phases below
|
|
28
|
+
for the work that belongs to it: its steps run in their declared order, each with
|
|
29
|
+
its own gate (`require_approval`, `notify_only`, `auto`) applied like a checkpoint,
|
|
30
|
+
after that pack's intake when one is declared. The generic phases still cover the
|
|
31
|
+
work no pack pipeline claims.
|
|
32
|
+
|
|
27
33
|
For a project requiring the full pipeline:
|
|
28
34
|
|
|
29
35
|
#### Phase 1: Discovery
|
|
36
|
+
0. **Intake of every pack the request involves** → For each such pack that declares an `intake` (the file sits in its installed pack directory), run the `bmad-plus-intake` protocol: `plan`, ask at most `max_per_message` questions in the user's language, `record` each answer, default or `UNKNOWN`, until `plan` says ready, then `render` the brief. The brief is an input of every later step; a pack with a must-have still open is not started.
|
|
30
37
|
1. **Strategist (Analyst role)** → Brainstorming & domain research
|
|
31
38
|
2. **Strategist (PM role)** → Product brief
|
|
32
39
|
3. **Strategist (PM role)** → PRD creation
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: bmad-plus-intake
|
|
3
|
+
description: Ask a user the questions a pack needs before it acts, a few at a time and in the user's language, record every answer, proposed default or unknown with its risk, and render the brief the pack works from. Use when a pack declares an intake, when a pipeline or a swarm is about to start, when a request lacks what the pack must know, or when someone says "what do you need from me".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Pack intake
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
A pack acts on what it knows. An intake is the list of what it must know before it starts:
|
|
11
|
+
each question marked must-have or not, with a default where one is honest and the risk the
|
|
12
|
+
pack runs when the answer stays unknown. The host asks, the user answers, the CLI keeps the
|
|
13
|
+
book, and the rendered brief becomes the contract for everything the pack does next.
|
|
14
|
+
|
|
15
|
+
Three files: the pack's **intake** (`intake.yaml`, shipped with the pack), the **answers**
|
|
16
|
+
(`.json`, written only through the CLI) and the **brief** (`.md`, rendered from both).
|
|
17
|
+
Formats and one example each: `ref/intake-format.md`.
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
intake.yaml ─► plan ─► ask (≤ max_per_message) ─► record ─► plan says ready ─► render ─► brief.md
|
|
21
|
+
▲ │
|
|
22
|
+
└──────────── not ready yet ◄──────────┘
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## When to activate
|
|
26
|
+
|
|
27
|
+
- A pack with an `intake` field in the registry is about to run its pipeline or start a swarm.
|
|
28
|
+
- The spine's Project Context names a pack that drives skills, and the request is thin.
|
|
29
|
+
- The user asks what is needed, or an agent is about to guess at something the user knows.
|
|
30
|
+
|
|
31
|
+
Never start a swarm or a pipeline for a pack while one of its must-haves is neither answered
|
|
32
|
+
nor marked unknown with its risk. Never invent an answer.
|
|
33
|
+
|
|
34
|
+
## Protocol
|
|
35
|
+
|
|
36
|
+
1. **Locate the files.** The intake is `.agents/skills/<pack_dir>/<intake>` as the registry
|
|
37
|
+
declares it. Keep the answers next to the pack's output, for example
|
|
38
|
+
`_bmad-output/<pack>/intake.json`; the brief goes where the pack's first step reads it.
|
|
39
|
+
2. **Plan.** `bmad-plus intake plan --intake FILE --answers FILE --json`. Exit 0 means ready;
|
|
40
|
+
exit 2 means a must-have is open. `next` lists what to ask now, must-haves first, in the
|
|
41
|
+
file's order, never more than `max_per_message`.
|
|
42
|
+
3. **Ask in the user's language** (`language: user`) or in the tag the intake names. One
|
|
43
|
+
message, the questions of `next`, each with its choices or bounds when it has them, and
|
|
44
|
+
the default where one exists ("5 unless you say otherwise"). Do not pad, do not rephrase
|
|
45
|
+
the question's intent, do not ask what is already recorded.
|
|
46
|
+
4. **Record what you heard.** `bmad-plus intake record --intake FILE --answers FILE --set
|
|
47
|
+
id=VALUE ... --json`. A value is checked against the question's kind and bounds and
|
|
48
|
+
refused when it does not fit; ask again rather than coerce. When the user does not know,
|
|
49
|
+
`--set id=UNKNOWN` records the question's risk with it. When the user accepts the proposed
|
|
50
|
+
default without choosing, `--default id` records it as `defaulted`; a value the user
|
|
51
|
+
actually chose, even equal to the default, is recorded with `--set` as `answered`.
|
|
52
|
+
5. **Loop** to step 2 until `plan` says ready. Stop asking then, even if optional questions
|
|
53
|
+
remain: say which ones stay open and move on unless the user wants to continue.
|
|
54
|
+
6. **Render.** `bmad-plus intake render --intake FILE --answers FILE --out brief.md --json`.
|
|
55
|
+
The brief lists every section, every answer with its status and must-have mark, and an
|
|
56
|
+
"Open questions" list with the risks. Hand the brief to the pack's pipeline or swarm as
|
|
57
|
+
their input; quote the open risks in the first deliverable.
|
|
58
|
+
|
|
59
|
+
## Rules
|
|
60
|
+
|
|
61
|
+
- A `defaulted` value is a proposal the user let stand, not a fact the user gave. The brief
|
|
62
|
+
says so, and a deliverable built on it says so too.
|
|
63
|
+
- An `unknown` answer carries its risk everywhere the answer would have been used.
|
|
64
|
+
- Answers are written only through `record`; never edit the JSON by hand, never write the
|
|
65
|
+
brief by hand. A changed intake file invalidates an answers file that no longer fits it;
|
|
66
|
+
`plan` reports the problem, `record --reset` starts the file again, empty, for the same
|
|
67
|
+
intake id (a file that belongs to another intake is never reset over), and the questions
|
|
68
|
+
are asked again.
|
|
69
|
+
- `render` only overwrites a brief it wrote before for the same intake (the second line of
|
|
70
|
+
the file is the ownership marker); `record` only overwrites an answers file of the same
|
|
71
|
+
intake. Neither writes under `.git/`, `_bmad/`, `.bmad-plus/` or `node_modules/`, nor
|
|
72
|
+
through a symlink. A user's value is printed as an indented block under `Answer:`, so what
|
|
73
|
+
the user typed never becomes a heading or a list of the brief.
|
|
74
|
+
- `bmad-plus intake check FILE --json` validates an intake file; the BMAD+ build runs the
|
|
75
|
+
same validator on every intake a pack declares.
|
|
76
|
+
|
|
77
|
+
## Commands
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
bmad-plus intake check FILE --json
|
|
81
|
+
bmad-plus intake plan --intake FILE --answers FILE --json
|
|
82
|
+
bmad-plus intake record --intake FILE --answers FILE --set id=VALUE [--set id=UNKNOWN] [--default id] --json
|
|
83
|
+
bmad-plus intake render --intake FILE --answers FILE --out brief.md --json
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Paths are relative to the project (`--directory`, default the current directory) and must
|
|
87
|
+
stay inside it. Exit codes: 0 done, 1 invalid file or value, 2 not ready (`plan`).
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# Intake file formats
|
|
2
|
+
|
|
3
|
+
Validator: `tools/build/intake-contract.js` (shipped with BMAD+; run by `bmad-plus intake
|
|
4
|
+
check` and by the BMAD+ build on every declared intake). Unknown fields are refused.
|
|
5
|
+
|
|
6
|
+
## 1. Intake (`intake.yaml`, shipped by the pack)
|
|
7
|
+
|
|
8
|
+
```yaml
|
|
9
|
+
schema_version: 1
|
|
10
|
+
id: shop-brief # lowercase slug, unique per pack
|
|
11
|
+
pack: shop # the pack id that declares `intake:` in the registry
|
|
12
|
+
title: Shop brief
|
|
13
|
+
language: user # ask in the user's language, or a tag such as fr or en-GB
|
|
14
|
+
max_per_message: 4 # 1..20, default 6
|
|
15
|
+
sections:
|
|
16
|
+
- id: offer
|
|
17
|
+
title: What is sold
|
|
18
|
+
questions:
|
|
19
|
+
- id: product_kind
|
|
20
|
+
ask: What does the shop sell, one line?
|
|
21
|
+
kind: text
|
|
22
|
+
must_have: true
|
|
23
|
+
feeds: [brief.md#offer]
|
|
24
|
+
risk_if_unknown: Every page is written for a product nobody described.
|
|
25
|
+
- id: price_band
|
|
26
|
+
ask: Where do prices sit?
|
|
27
|
+
kind: choice
|
|
28
|
+
choices: [budget, mid, premium]
|
|
29
|
+
default: mid
|
|
30
|
+
feeds: [brief.md#offer]
|
|
31
|
+
- id: launch_in_days
|
|
32
|
+
ask: In how many days must it go live?
|
|
33
|
+
kind: number
|
|
34
|
+
min: 1
|
|
35
|
+
max: 365
|
|
36
|
+
- id: has_stock
|
|
37
|
+
ask: Is there stock to ship today?
|
|
38
|
+
kind: boolean
|
|
39
|
+
default: true
|
|
40
|
+
- id: markets
|
|
41
|
+
ask: Which countries are served?
|
|
42
|
+
kind: list
|
|
43
|
+
must_have: true
|
|
44
|
+
risk_if_unknown: Taxes, currencies and legal pages cannot be chosen.
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
- `kind`: `text`, `choice` (needs at least two distinct `choices`), `number` (optional `min`,
|
|
48
|
+
`max`), `boolean`, `list` (of texts).
|
|
49
|
+
- `must_have: true` requires `risk_if_unknown` and forbids `default`: the user answers it or
|
|
50
|
+
marks it unknown. A question that is not must-have may carry a `default`, valid for its kind.
|
|
51
|
+
- `feeds` names the artifact anchors the answer fills (`file#anchor`); informative.
|
|
52
|
+
- Question ids are `snake_case` and unique across the whole file; section ids are slugs.
|
|
53
|
+
|
|
54
|
+
## 2. Answers (`.json`, written by `bmad-plus intake record`)
|
|
55
|
+
|
|
56
|
+
```json
|
|
57
|
+
{
|
|
58
|
+
"schemaVersion": 1,
|
|
59
|
+
"intake": "shop-brief",
|
|
60
|
+
"answers": {
|
|
61
|
+
"product_kind": { "value": "Hand-poured soy candles", "status": "answered" },
|
|
62
|
+
"price_band": { "value": "mid", "status": "defaulted" },
|
|
63
|
+
"markets": { "status": "unknown", "risk": "Taxes, currencies and legal pages cannot be chosen." }
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
- Statuses: `answered` (the user said it), `defaulted` (the proposed default stood), `unknown`
|
|
69
|
+
(the user does not know; `risk` copies the question's `risk_if_unknown`). Nothing else.
|
|
70
|
+
- A key must be a question id of the intake; a value must fit the question's kind and bounds;
|
|
71
|
+
a `defaulted` value equals the question's default. A question not yet asked has no entry.
|
|
72
|
+
|
|
73
|
+
## 3. Brief (`.md`, written by `bmad-plus intake render`)
|
|
74
|
+
|
|
75
|
+
```markdown
|
|
76
|
+
# Shop brief
|
|
77
|
+
<!-- owned by bmad-plus intake shop-brief; written by bmad-plus intake render, do not edit -->
|
|
78
|
+
|
|
79
|
+
Intake `shop-brief` of pack `shop` — 1 answered, 1 defaulted, 1 unknown, 2 not asked yet. Not ready: a must-have is open.
|
|
80
|
+
|
|
81
|
+
## What is sold
|
|
82
|
+
|
|
83
|
+
### product_kind (must-have)
|
|
84
|
+
|
|
85
|
+
What does the shop sell, one line?
|
|
86
|
+
|
|
87
|
+
Answer:
|
|
88
|
+
Hand-poured soy candles
|
|
89
|
+
Feeds: brief.md#offer
|
|
90
|
+
|
|
91
|
+
### price_band
|
|
92
|
+
|
|
93
|
+
Where do prices sit?
|
|
94
|
+
|
|
95
|
+
Answer (proposed default, not confirmed by the user):
|
|
96
|
+
mid
|
|
97
|
+
Feeds: brief.md#offer
|
|
98
|
+
|
|
99
|
+
...
|
|
100
|
+
|
|
101
|
+
## Open questions
|
|
102
|
+
|
|
103
|
+
- markets (must-have): unknown — risk: Taxes, currencies and legal pages cannot be chosen.
|
|
104
|
+
- launch_in_days: not asked yet
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
The first paragraph states readiness; a pack reads "Ready." before it starts. The second
|
|
108
|
+
line is the ownership marker: `render` overwrites an existing file only when it starts with
|
|
109
|
+
the marker of the same intake. Values are printed as a block indented by four spaces, one
|
|
110
|
+
line per list item and per line of a multi-line text, so a value never opens a heading or a
|
|
111
|
+
list of its own. Text and list values may hold line breaks and tabs; any other control
|
|
112
|
+
character is refused.
|