bmad-plus 0.13.0 → 0.16.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.
Files changed (135) hide show
  1. package/CHANGELOG.md +74 -0
  2. package/README.md +113 -487
  3. package/SECURITY.md +71 -0
  4. package/THIRD-PARTY-LICENSES.md +349 -0
  5. package/osint-agent-package/README.md +1 -1
  6. package/package.json +14 -3
  7. package/readme-international/README.de.md +18 -8
  8. package/readme-international/README.es.md +19 -9
  9. package/readme-international/README.fr.md +18 -8
  10. package/src/bmad-plus/agents/agent-architect-dev/SKILL.md +11 -13
  11. package/src/bmad-plus/agents/agent-orchestrator/SKILL.md +148 -9
  12. package/src/bmad-plus/agents/agent-quality/SKILL.md +41 -11
  13. package/src/bmad-plus/data/role-triggers.yaml +19 -0
  14. package/src/bmad-plus/module-help.csv +1 -0
  15. package/src/bmad-plus/module.yaml +1 -0
  16. package/src/bmad-plus/packs/pack-dev-studio/README.md +133 -141
  17. package/src/bmad-plus/packs/pack-dev-studio/SKILL.md +49 -0
  18. package/src/bmad-plus/packs/pack-dev-studio/categories/analysis/analyst-agent.md +35 -60
  19. package/src/bmad-plus/packs/pack-dev-studio/categories/analysis/document-project.md +59 -59
  20. package/src/bmad-plus/packs/pack-dev-studio/categories/analysis/domain-research.md +55 -93
  21. package/src/bmad-plus/packs/pack-dev-studio/categories/analysis/market-research.md +58 -93
  22. package/src/bmad-plus/packs/pack-dev-studio/categories/analysis/prfaq.md +55 -132
  23. package/src/bmad-plus/packs/pack-dev-studio/categories/analysis/product-brief.md +63 -78
  24. package/src/bmad-plus/packs/pack-dev-studio/categories/analysis/tech-writer-agent.md +54 -69
  25. package/src/bmad-plus/packs/pack-dev-studio/categories/analysis/technical-research.md +54 -93
  26. package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/architect-agent.md +32 -60
  27. package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/create-architecture.md +67 -71
  28. package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/create-epics-stories.md +61 -90
  29. package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/generate-project-context.md +56 -78
  30. package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/implementation-readiness.md +55 -88
  31. package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/steps/step-01-init.md +20 -153
  32. package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/steps/step-01b-continue.md +20 -173
  33. package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/steps/step-02-context.md +14 -220
  34. package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/steps/step-03-starter.md +20 -329
  35. package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/steps/step-04-decisions.md +15 -314
  36. package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/steps/step-05-patterns.md +15 -355
  37. package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/steps/step-06-structure.md +15 -375
  38. package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/steps/step-07-validation.md +14 -357
  39. package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/steps/step-08-complete.md +13 -78
  40. package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/checkpoint-preview.md +52 -65
  41. package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/code-review-steps/step-01-gather-context.md +14 -81
  42. package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/code-review-steps/step-02-review.md +14 -31
  43. package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/code-review-steps/step-03-triage.md +14 -45
  44. package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/code-review-steps/step-04-present.md +13 -128
  45. package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/code-review.md +61 -87
  46. package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/correct-course.md +55 -298
  47. package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/create-story.md +54 -426
  48. package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/dev-agent.md +48 -69
  49. package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/dev-story-checklist.md +24 -80
  50. package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/dev-story.md +64 -482
  51. package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/investigate.md +50 -184
  52. package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/qa-e2e-tests.md +57 -173
  53. package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/quick-dev.md +56 -108
  54. package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/retrospective.md +54 -1509
  55. package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/sprint-planning.md +54 -296
  56. package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/sprint-status.md +41 -283
  57. package/src/bmad-plus/packs/pack-dev-studio/categories/planning/create-prd.md +58 -18
  58. package/src/bmad-plus/packs/pack-dev-studio/categories/planning/create-ux-design.md +103 -72
  59. package/src/bmad-plus/packs/pack-dev-studio/categories/planning/edit-prd.md +55 -27
  60. package/src/bmad-plus/packs/pack-dev-studio/categories/planning/pm-agent.md +34 -60
  61. package/src/bmad-plus/packs/pack-dev-studio/categories/planning/prd.md +46 -87
  62. package/src/bmad-plus/packs/pack-dev-studio/categories/planning/steps/step-01-init.md +10 -0
  63. package/src/bmad-plus/packs/pack-dev-studio/categories/planning/ux-designer-agent.md +30 -60
  64. package/src/bmad-plus/packs/pack-dev-studio/categories/planning/validate-prd.md +57 -27
  65. package/src/bmad-plus/packs/pack-dev-studio/categories/utilities/advanced-elicitation.md +47 -138
  66. package/src/bmad-plus/packs/pack-dev-studio/categories/utilities/adversarial-review.md +48 -34
  67. package/src/bmad-plus/packs/pack-dev-studio/categories/utilities/bmad-help.md +51 -68
  68. package/src/bmad-plus/packs/pack-dev-studio/categories/utilities/brainstorming.md +46 -3
  69. package/src/bmad-plus/packs/pack-dev-studio/categories/utilities/customize.md +68 -109
  70. package/src/bmad-plus/packs/pack-dev-studio/categories/utilities/distillator.md +53 -174
  71. package/src/bmad-plus/packs/pack-dev-studio/categories/utilities/edge-case-hunter.md +39 -53
  72. package/src/bmad-plus/packs/pack-dev-studio/categories/utilities/editorial-review-prose.md +45 -83
  73. package/src/bmad-plus/packs/pack-dev-studio/categories/utilities/editorial-review-structure.md +45 -176
  74. package/src/bmad-plus/packs/pack-dev-studio/categories/utilities/index-docs.md +45 -63
  75. package/src/bmad-plus/packs/pack-dev-studio/categories/utilities/party-mode.md +53 -124
  76. package/src/bmad-plus/packs/pack-dev-studio/categories/utilities/shard-doc.md +44 -100
  77. package/src/bmad-plus/packs/pack-dev-studio/dev-studio-orchestrator.md +56 -116
  78. package/src/bmad-plus/packs/pack-dev-studio/shared/architecture-decision-template.md +49 -12
  79. package/src/bmad-plus/packs/pack-dev-studio/shared/bwml-spec.md +51 -328
  80. package/src/bmad-plus/packs/pack-dev-studio/shared/catalog.json +489 -0
  81. package/src/bmad-plus/packs/pack-dev-studio/shared/execution.md +69 -0
  82. package/src/bmad-plus/packs/pack-dev-studio/shared/module-help.csv +39 -32
  83. package/src/bmad-plus/packs/pack-dev-studio/upstream-sync.yaml +85 -14
  84. package/src/bmad-plus/packs/pack-memory/README.md +35 -4
  85. package/src/bmad-plus/packs/pack-memory/memory-orchestrator.md +33 -6
  86. package/src/bmad-plus/packs/pack-memory/shared/karpathy-guardrails.md +3 -3
  87. package/src/bmad-plus/packs/pack-memory/shared/memory-protocol.md +27 -3
  88. package/src/bmad-plus/packs/pack-memory/zecher-agent.md +18 -2
  89. package/src/bmad-plus/packs/pack-seo/SKILL.md +27 -1
  90. package/src/bmad-plus/packs/pack-seo/seo-chief.md +16 -1
  91. package/src/bmad-plus/packs/pack-seo/seo-judge.md +12 -0
  92. package/src/bmad-plus/packs/pack-seo/seo-scout.md +12 -0
  93. package/src/bmad-plus/skills/bmad-plus-autopilot/SKILL.md +49 -12
  94. package/src/bmad-plus/skills/bmad-plus-parallel/SKILL.md +17 -3
  95. package/src/bmad-plus/skills/bmad-plus-sync/SKILL.md +76 -65
  96. package/src/bmad-plus/skills/bmad-plus-uat/SKILL.md +144 -0
  97. package/src/bmad-plus/skills/bmad-plus-uat/ref/uat-results.schema.json +60 -0
  98. package/src/bmad-plus/skills/bmad-plus-uat/ref/uat-spec.schema.json +121 -0
  99. package/src/bmad-plus/skills/bmad-plus-uat/ref/uat-triage.schema.json +60 -0
  100. package/src/bmad-plus/skills/bmad-plus-uat/template/page.html +552 -0
  101. package/src/bmad-plus/skills/bmad-plus-uat/template/strings.json +362 -0
  102. package/src/bmad-plus/skills/dev-studio/SKILL.md +19 -0
  103. package/tools/build/check-install-contract.js +367 -17
  104. package/tools/build/generate.js +229 -40
  105. package/tools/build/generated-adapters/.codex/AGENTS.md +1 -1
  106. package/tools/build/generated-adapters/.cursor/rules/bmad-plus.mdc +1 -1
  107. package/tools/build/generated-adapters/.opencode/AGENTS.md +1 -1
  108. package/tools/build/generated-adapters/AGENTS.md +1 -1
  109. package/tools/build/generated-adapters/CLAUDE.md +1 -1
  110. package/tools/build/generated-adapters/CONVENTIONS.md +1 -1
  111. package/tools/build/generated-adapters/GEMINI.md +1 -1
  112. package/tools/build/pack-delivery.js +78 -0
  113. package/tools/cli/bmad-plus-cli.js +15 -12
  114. package/tools/cli/commands/doctor.js +50 -189
  115. package/tools/cli/commands/install.js +22 -3
  116. package/tools/cli/commands/memory-journal-cmd.js +119 -19
  117. package/tools/cli/commands/nexus.js +111 -0
  118. package/tools/cli/commands/studio.js +68 -0
  119. package/tools/cli/commands/uat.js +389 -0
  120. package/tools/cli/lib/README-memory-journal.md +19 -8
  121. package/tools/cli/lib/installation-health.js +366 -0
  122. package/tools/cli/lib/memory-journal.js +0 -0
  123. package/tools/cli/lib/memory-outcomes.js +293 -0
  124. package/tools/cli/lib/memory-store.js +139 -0
  125. package/tools/cli/lib/nexus-process.js +377 -0
  126. package/tools/cli/lib/nexus.js +1532 -0
  127. package/tools/cli/lib/pack-copy.js +39 -11
  128. package/tools/cli/lib/packs.js +134 -11
  129. package/tools/cli/lib/python-health.js +233 -0
  130. package/tools/cli/lib/python-provision.js +2 -2
  131. package/tools/cli/lib/studio.js +310 -0
  132. package/tools/cli/lib/uat.js +869 -0
  133. package/tools/maintain/upstream-candidate.js +456 -0
  134. package/tools/release/publication-content.js +903 -0
  135. package/tools/release/supply-chain.js +282 -0
@@ -0,0 +1,310 @@
1
+ /** Read-only Dev Studio resource resolution; execution belongs to the host. */
2
+ 'use strict';
3
+
4
+ const fs = require('node:fs');
5
+ const path = require('node:path');
6
+ const crypto = require('node:crypto');
7
+ const yaml = require('js-yaml');
8
+ const { safeTarget } = require('../../build/generate-adapters');
9
+
10
+ const PACK = '.agents/skills/pack-dev-studio';
11
+ const MAX_FILE = 256 * 1024;
12
+ const MAX_CONTEXT = 2 * 1024 * 1024;
13
+ const hash = (bytes) => crypto.createHash('sha256').update(bytes).digest('hex');
14
+
15
+ function relativePath(file) {
16
+ if (
17
+ typeof file !== 'string' ||
18
+ !file ||
19
+ /[\\:\0?#{}]/.test(file) ||
20
+ file.split('/').some((part) => !part || part === '.' || part === '..')
21
+ ) {
22
+ throw new Error('Expected a portable relative file path: ' + String(file));
23
+ }
24
+ return file;
25
+ }
26
+
27
+ function target(root, file) {
28
+ relativePath(file);
29
+ const result = safeTarget(root, file);
30
+ let parent = path.resolve(root);
31
+ for (const part of file.split('/')) {
32
+ if (!fs.existsSync(parent)) break;
33
+ const names = fs.readdirSync(parent);
34
+ if (!names.includes(part) && names.some((name) => name.toLowerCase() === part.toLowerCase())) {
35
+ throw new Error('Path case mismatch: ' + file);
36
+ }
37
+ parent = path.join(parent, part);
38
+ }
39
+ return result;
40
+ }
41
+
42
+ function readText(root, file, limit = MAX_FILE) {
43
+ const resolved = target(root, file);
44
+ const stat = fs.statSync(resolved);
45
+ if (!stat.isFile() || stat.size > limit) throw new Error('Resource is not bounded text: ' + file);
46
+ const bytes = fs.readFileSync(resolved);
47
+ if (bytes.includes(0) || bytes.length > limit)
48
+ throw new Error('Resource is not bounded text: ' + file);
49
+ const content = bytes.toString('utf8');
50
+ if (!Buffer.from(content).equals(bytes)) throw new Error('Resource is not UTF-8: ' + file);
51
+ return { path: file, sha256: hash(bytes), content };
52
+ }
53
+
54
+ function readJson(root, file) {
55
+ try {
56
+ return JSON.parse(readText(root, file).content);
57
+ } catch (error) {
58
+ throw new Error(file + ': ' + error.message, { cause: error });
59
+ }
60
+ }
61
+
62
+ function loadCatalog(packRoot) {
63
+ const catalog = readJson(packRoot, 'shared/catalog.json');
64
+ if (
65
+ catalog.schemaVersion !== 1 ||
66
+ !Array.isArray(catalog.agents) ||
67
+ !Array.isArray(catalog.workflows) ||
68
+ !Array.isArray(catalog.compatibility) ||
69
+ !catalog.agents.length ||
70
+ !catalog.workflows.length
71
+ ) {
72
+ throw new Error('Unsupported Dev Studio catalog');
73
+ }
74
+ catalog.compatibility.forEach(relativePath);
75
+ const agents = new Set();
76
+ const routes = new Set();
77
+ const entries = new Set();
78
+ for (const agent of catalog.agents) {
79
+ if (
80
+ !agent ||
81
+ !/^[a-z][a-z0-9-]*$/.test(agent.id) ||
82
+ agents.has(agent.id) ||
83
+ typeof agent.persona !== 'string' ||
84
+ !agent.persona.trim()
85
+ )
86
+ throw new Error('Invalid or duplicate persona');
87
+ relativePath(agent.path);
88
+ if (entries.has(agent.path)) throw new Error('Duplicate catalog entry: ' + agent.path);
89
+ entries.add(agent.path);
90
+ agents.add(agent.id);
91
+ }
92
+ for (const workflow of catalog.workflows) {
93
+ if (
94
+ !workflow ||
95
+ !/^[a-z][a-z0-9-]*$/.test(workflow.id) ||
96
+ !agents.has(workflow.agent) ||
97
+ !['request', 'artifact', 'project', 'none'].includes(workflow.input) ||
98
+ !Array.isArray(workflow.aliases) ||
99
+ !Array.isArray(workflow.resources)
100
+ ) {
101
+ throw new Error('Invalid workflow declaration');
102
+ }
103
+ relativePath(workflow.path);
104
+ if (entries.has(workflow.path)) throw new Error('Duplicate catalog entry: ' + workflow.path);
105
+ entries.add(workflow.path);
106
+ for (const resource of workflow.resources) relativePath(resource);
107
+ for (const route of [workflow.id, ...workflow.aliases]) {
108
+ if (typeof route !== 'string' || !/^[a-z][a-z0-9-]*$/.test(route) || routes.has(route)) {
109
+ throw new Error('Invalid or duplicate workflow route: ' + route);
110
+ }
111
+ routes.add(route);
112
+ }
113
+ }
114
+ return catalog;
115
+ }
116
+
117
+ /** Inline and reference-style Markdown links are packaged dependencies. */
118
+ function localLinks(content, file) {
119
+ const destinations = [
120
+ ...Array.from(
121
+ content.matchAll(/!?\[[^\]\n]*\]\(<?([^\s)>]+)>?(?:\s+"[^"]*")?\)/g),
122
+ (m) => m[1]
123
+ ),
124
+ ...Array.from(content.matchAll(/^\s{0,3}\[[^\]\n]+\]:\s*<?([^\s>]+)>?/gm), (m) => m[1]),
125
+ ];
126
+ return destinations
127
+ .filter((link) => !/^(?:https?:|mailto:|#)/i.test(link))
128
+ .map((link) => {
129
+ const clean = decodeURIComponent(link.split('#')[0]);
130
+ if (!clean || /[\\:\0?{}]/.test(clean) || path.posix.isAbsolute(clean)) {
131
+ throw new Error('Unsupported resource link in ' + file + ': ' + link);
132
+ }
133
+ return relativePath(path.posix.normalize(path.posix.join(path.posix.dirname(file), clean)));
134
+ });
135
+ }
136
+
137
+ function validatePack(packRoot, expected) {
138
+ const catalog = loadCatalog(packRoot);
139
+ if (expected) {
140
+ const workflows = Object.values(expected.categories)
141
+ .flatMap((category) => category.workflows)
142
+ .sort();
143
+ if (
144
+ JSON.stringify(workflows) !== JSON.stringify(catalog.workflows.map((w) => w.id).sort()) ||
145
+ JSON.stringify([...expected.sub_agents].sort()) !==
146
+ JSON.stringify(catalog.agents.map((a) => a.id).sort())
147
+ ) {
148
+ throw new Error('Dev Studio catalog disagrees with registry routes');
149
+ }
150
+ }
151
+ const queue = [
152
+ 'SKILL.md',
153
+ 'README.md',
154
+ 'dev-studio-orchestrator.md',
155
+ 'shared/execution.md',
156
+ ...catalog.compatibility,
157
+ ...catalog.agents.map((a) => a.path),
158
+ ...catalog.workflows.flatMap((w) => [w.path, ...w.resources]),
159
+ ];
160
+ const visited = new Set();
161
+ let bytes = 0;
162
+ while (queue.length) {
163
+ const file = queue.shift();
164
+ if (visited.has(file)) continue;
165
+ if (visited.size >= 256) throw new Error('Too many Dev Studio resources');
166
+ const resource = readText(packRoot, file);
167
+ bytes += Buffer.byteLength(resource.content);
168
+ if (bytes > MAX_CONTEXT) throw new Error('Dev Studio resource graph is too large');
169
+ visited.add(file);
170
+ if (file.endsWith('.md')) {
171
+ if (
172
+ /\{(?:workflow|agent)\.[^}]+\}|\{(?:project-root|planning_artifacts|communication_language)\}/.test(
173
+ resource.content
174
+ )
175
+ ) {
176
+ throw new Error('Unresolved runtime declaration: ' + file);
177
+ }
178
+ queue.push(...localLinks(resource.content, file));
179
+ }
180
+ }
181
+ return { catalog, resources: [...visited].sort() };
182
+ }
183
+
184
+ function resolveConfig(projectDir) {
185
+ const file = '_bmad/config.yaml';
186
+ const location = target(projectDir, file);
187
+ let supplied = {};
188
+ let source = null;
189
+ if (fs.existsSync(location)) {
190
+ source = readText(projectDir, file, 64 * 1024);
191
+ try {
192
+ supplied = yaml.load(source.content);
193
+ } catch (error) {
194
+ throw new Error(file + ': ' + error.message, { cause: error });
195
+ }
196
+ if (!supplied || typeof supplied !== 'object' || Array.isArray(supplied)) {
197
+ throw new Error(file + ' must be a YAML mapping');
198
+ }
199
+ }
200
+ const config = {
201
+ user_name: 'user',
202
+ communication_language: 'English',
203
+ document_output_language: 'English',
204
+ output_folder: '_bmad-output',
205
+ project_name: path.basename(projectDir),
206
+ };
207
+ const defaultsUsed = [];
208
+ for (const key of Object.keys(config)) {
209
+ if (Object.hasOwn(supplied, key)) {
210
+ if (typeof supplied[key] !== 'string' || !supplied[key].trim()) {
211
+ throw new Error(file + ': ' + key + ' must be a nonempty string');
212
+ }
213
+ config[key] = supplied[key];
214
+ } else defaultsUsed.push(key);
215
+ }
216
+ relativePath(config.output_folder);
217
+ return { values: config, defaultsUsed, source };
218
+ }
219
+
220
+ function installedPack(projectDir) {
221
+ // Validate ancestors through an entry path before using the pack as a root.
222
+ target(projectDir, PACK + '/SKILL.md');
223
+ const packRoot = path.join(projectDir, PACK);
224
+ if (!fs.existsSync(packRoot))
225
+ throw new Error('Dev Studio is not installed. Run bmad-plus install --packs core,dev-studio');
226
+ return packRoot;
227
+ }
228
+
229
+ function prepare({
230
+ projectDir = process.cwd(),
231
+ workflow: route,
232
+ request = '',
233
+ inputs = [],
234
+ packRoot,
235
+ } = {}) {
236
+ projectDir = path.resolve(projectDir);
237
+ if (!fs.statSync(projectDir).isDirectory()) throw new Error('Project must be a directory');
238
+ packRoot = packRoot || installedPack(projectDir);
239
+ const { catalog } = validatePack(packRoot);
240
+ const workflow = catalog.workflows.find((w) => w.id === route || w.aliases.includes(route));
241
+ if (!workflow) throw new Error('Unknown Dev Studio workflow: ' + route);
242
+ if (
243
+ typeof request !== 'string' ||
244
+ Buffer.byteLength(request) > MAX_FILE ||
245
+ !Array.isArray(inputs) ||
246
+ inputs.length > 32
247
+ ) {
248
+ throw new Error('Invalid or oversized workflow inputs');
249
+ }
250
+ const config = resolveConfig(projectDir);
251
+ const loadedInputs = [...new Set(inputs)].map((file) => readText(projectDir, file));
252
+ const agent = catalog.agents.find((a) => a.id === workflow.agent);
253
+ const routes = new Set([
254
+ ...catalog.agents.map((a) => a.path),
255
+ ...catalog.workflows.map((w) => w.path),
256
+ 'SKILL.md',
257
+ 'README.md',
258
+ 'dev-studio-orchestrator.md',
259
+ 'shared/catalog.json',
260
+ ]);
261
+ const queue = ['shared/execution.md', agent.path, workflow.path, ...workflow.resources];
262
+ const instructions = [];
263
+ const loaded = new Set();
264
+ while (queue.length) {
265
+ const file = queue.shift();
266
+ if (loaded.has(file)) continue;
267
+ loaded.add(file);
268
+ const resource = readText(packRoot, file);
269
+ instructions.push(resource);
270
+ if (file.endsWith('.md'))
271
+ queue.push(...localLinks(resource.content, file).filter((link) => !routes.has(link)));
272
+ }
273
+ const outputPath = `${config.values.output_folder}/dev-studio/${workflow.id}.md`;
274
+ const outputTarget = target(projectDir, outputPath);
275
+ const previousReport = fs.existsSync(outputTarget) ? readText(projectDir, outputPath) : null;
276
+ const size = [
277
+ ...loadedInputs,
278
+ ...instructions,
279
+ ...(previousReport ? [previousReport] : []),
280
+ ].reduce(
281
+ (total, item) => total + Buffer.byteLength(item.content),
282
+ Buffer.byteLength(request) + Buffer.byteLength(config.source?.content || '')
283
+ );
284
+ if (size > MAX_CONTEXT) throw new Error('Prepared context exceeds 2 MiB');
285
+ const missingInputs =
286
+ workflow.input === 'artifact' && !loadedInputs.length
287
+ ? ['Supply a project artifact with --input RELATIVE_FILE.']
288
+ : ['request', 'project'].includes(workflow.input) && !request.trim() && !loadedInputs.length
289
+ ? ['Supply the task scope with --request TEXT or --input RELATIVE_FILE.']
290
+ : [];
291
+ return {
292
+ schemaVersion: 1,
293
+ status: missingInputs.length ? 'needs-input' : 'ready',
294
+ execution: 'host-managed',
295
+ executed: false,
296
+ workflow: workflow.id,
297
+ agent: agent.persona,
298
+ catalogSha256: readText(packRoot, 'shared/catalog.json').sha256,
299
+ projectDir,
300
+ config,
301
+ request,
302
+ inputs: loadedInputs,
303
+ instructions,
304
+ outputPath,
305
+ previousReport,
306
+ missingInputs,
307
+ };
308
+ }
309
+
310
+ module.exports = { loadCatalog, localLinks, validatePack, resolveConfig, installedPack, prepare };