@bicon/mcp-composer 0.4.0 → 0.6.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 (3) hide show
  1. package/README.md +2 -2
  2. package/dist/index.mjs +384 -10
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -24,7 +24,7 @@ via API keys is a separate, security-reviewed phase.
24
24
  | Name | What it does |
25
25
  |---|---|
26
26
  | resource `initiative://schema` / tool `get_initiative_schema` | The field catalog: required fields, enum values, the four dimensions with their named sub-dimensions (EN/DE labels + help text, plus the wording the app uses in digital / innovation portfolios), the exact shape of every optional section, the EU-AI-Act vocabularies, and the handoff steps. **Read this first.** |
27
- | `assemble_initiative` | Compact spec (metadata + named sub-ratings 0–100 + confidence per dimension + optional sections, optionally the organisation's `context`) → fully-formed initiative validated against the API contract (`CreateInitiativeBody` from `@workspace/api-zod`). Mints the initiative id and every nested row id (decision-log entries, status reports, incidents — a client never invents ids), **derives** the four dimension scores (the app's own scoring function), accepts dates as dd/mm/yyyy, dd.mm.yyyy or yyyy-mm-dd, returns `{ok, initiative, derivedScores, warnings, errors, contextId}`. Pass `id` (an existing initiative's) only to **update** that initiative. |
27
+ | `assemble_initiative` | Compact spec (metadata + named sub-ratings 0–100 + confidence per dimension + optional sections, optionally the organisation's `context`) → fully-formed initiative validated against the API contract (`CreateInitiativeBody` from `@workspace/api-zod`). Mints the initiative id and every nested row id (decision-log entries, status reports, milestones, incidents — a client never invents ids), **derives** the four dimension scores (the app's own scoring function), accepts dates as dd/mm/yyyy, dd.mm.yyyy or yyyy-mm-dd, returns `{ok, initiative, derivedScores, warnings, errors, contextId}`. Pass `id` (an existing initiative's) only to **update** that initiative. |
28
28
  | `export_initiative_file` | Takes the **same compact spec**, assembles it and wraps the result in the app's single-initiative JSON envelope; returns `{ok, filename, json, importInstructions, derivedScores, warnings}`. There is one pipeline — a hand-edited initiative object is not an input, so client-supplied scores or unknown keys can never bypass assembly. |
29
29
  | `read_portfolio_context` | Takes the organisation's **portfolio-context file** (see below) and returns the interview plan for that organisation — its own labels, help texts and rating notes per sub-dimension, which sub-dimensions are switched off, its business units, categories, tags, skills (id + name), non-archived initiatives (id + name) and the capability map's capabilities (id, name, domain, importance, current → target maturity; context version 2), currency, discount rate, whether the EU-AI-Act module is on — plus a short **contextId** that stands in for the file in the two other tools. |
30
30
  | `composer_version` | Returns `{composerVersion, capabilities}`. Every *successful* tool result also carries `composerVersion`. |
@@ -93,7 +93,7 @@ vocabularies (`aiActVocabularies` in the descriptor; the app drops unknown
93
93
  obligation keys and never shows unknown artifact keys), the score derivation —
94
94
  is checked in the assembler, which reports **all** problems of a call at once
95
95
  with the allowed values in the message (id shapes included). Row ids of
96
- decision-log entries, status reports and incidents are minted by the
96
+ decision-log entries, status reports, milestones and incidents are minted by the
97
97
  Composer — a client-supplied UUID is kept, anything else replaced — because
98
98
  the app keys those rows per initiative and a re-used id from another
99
99
  initiative is exactly what collided on import once.
package/dist/index.mjs CHANGED
@@ -12,7 +12,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
12
12
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
13
13
 
14
14
  // src/version.ts
15
- var COMPOSER_VERSION = true ? "0.4.0" : readPackageVersion();
15
+ var COMPOSER_VERSION = true ? "0.6.0" : readPackageVersion();
16
16
 
17
17
  // ../../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/external.js
18
18
  var external_exports = {};
@@ -4170,7 +4170,7 @@ var ListOrganizationMembersResponseItem = objectType({
4170
4170
  "email": stringType(),
4171
4171
  "displayName": stringType().nullable(),
4172
4172
  "role": enumType(["admin", "member", "viewer"]),
4173
- "permissions": arrayType(stringType()).describe("App-managed permission overrides on top of the fixed role (free-form strings, not a closed enum). Known keys: manage_skills, manage_ai_act, manage_metadata, manage_stage_gate, manage_economics, manage_decision_log, manage_dependencies, manage_required_skills, manage_scoring, manage_status_report, manage_prioritisation, manage_capabilities, manage_capability_impact.")
4173
+ "permissions": arrayType(stringType()).describe("App-managed permission overrides on top of the fixed role (free-form strings, not a closed enum). Known keys: manage_skills, manage_ai_act, manage_metadata, manage_stage_gate, manage_economics, manage_decision_log, manage_dependencies, manage_required_skills, manage_scoring, manage_status_report, manage_prioritisation, manage_capabilities, manage_capability_impact, manage_milestones, manage_risks.")
4174
4174
  });
4175
4175
  var ListOrganizationMembersResponse = arrayType(ListOrganizationMembersResponseItem);
4176
4176
  var SyncOrganizationMembersResponse = objectType({
@@ -4180,18 +4180,18 @@ var SyncOrganizationMembersResponse = objectType({
4180
4180
  var GetMyOrganizationAccessResponse = objectType({
4181
4181
  "userId": stringType().describe(`The caller's own local user id (matches AuthorRef.userId on initiatives), so the client can tell its own changes apart from a teammate's \u2014 e.g. to suppress the "updated by X" collaboration banner when an edit echoing back is the caller's own save.`),
4182
4182
  "role": enumType(["admin", "member", "viewer"]),
4183
- "permissions": arrayType(stringType()).describe("App-managed permission overrides on top of the fixed role (free-form strings, not a closed enum). Known keys: manage_skills, manage_ai_act, manage_metadata, manage_stage_gate, manage_economics, manage_decision_log, manage_dependencies, manage_required_skills, manage_scoring, manage_status_report, manage_prioritisation, manage_capabilities, manage_capability_impact."),
4183
+ "permissions": arrayType(stringType()).describe("App-managed permission overrides on top of the fixed role (free-form strings, not a closed enum). Known keys: manage_skills, manage_ai_act, manage_metadata, manage_stage_gate, manage_economics, manage_decision_log, manage_dependencies, manage_required_skills, manage_scoring, manage_status_report, manage_prioritisation, manage_capabilities, manage_capability_impact, manage_milestones, manage_risks."),
4184
4184
  "initiativeLimit": numberType().describe("The most initiatives this organisation may hold, archived ones included. Creating one more answers 507 with code initiative_limit_reached, so the client blocks New, Duplicate and Import up front.")
4185
4185
  });
4186
4186
  var UpdateOrganizationMemberPermissionsParams = objectType({
4187
4187
  "userId": coerce.string().uuid()
4188
4188
  });
4189
4189
  var UpdateOrganizationMemberPermissionsBody = objectType({
4190
- "permissions": arrayType(stringType()).describe("App-managed permission overrides on top of the fixed role (free-form strings, not a closed enum). Known keys: manage_skills, manage_ai_act, manage_metadata, manage_stage_gate, manage_economics, manage_decision_log, manage_dependencies, manage_required_skills, manage_scoring, manage_status_report, manage_prioritisation, manage_capabilities, manage_capability_impact.")
4190
+ "permissions": arrayType(stringType()).describe("App-managed permission overrides on top of the fixed role (free-form strings, not a closed enum). Known keys: manage_skills, manage_ai_act, manage_metadata, manage_stage_gate, manage_economics, manage_decision_log, manage_dependencies, manage_required_skills, manage_scoring, manage_status_report, manage_prioritisation, manage_capabilities, manage_capability_impact, manage_milestones, manage_risks.")
4191
4191
  });
4192
4192
  var UpdateOrganizationMemberPermissionsResponse = objectType({
4193
4193
  "userId": stringType().uuid(),
4194
- "permissions": arrayType(stringType()).describe("App-managed permission overrides on top of the fixed role (free-form strings, not a closed enum). Known keys: manage_skills, manage_ai_act, manage_metadata, manage_stage_gate, manage_economics, manage_decision_log, manage_dependencies, manage_required_skills, manage_scoring, manage_status_report, manage_prioritisation, manage_capabilities, manage_capability_impact.")
4194
+ "permissions": arrayType(stringType()).describe("App-managed permission overrides on top of the fixed role (free-form strings, not a closed enum). Known keys: manage_skills, manage_ai_act, manage_metadata, manage_stage_gate, manage_economics, manage_decision_log, manage_dependencies, manage_required_skills, manage_scoring, manage_status_report, manage_prioritisation, manage_capabilities, manage_capability_impact, manage_milestones, manage_risks.")
4195
4195
  });
4196
4196
  var ListPermissionProfilesResponseItem = objectType({
4197
4197
  "id": stringType().uuid(),
@@ -4280,6 +4280,24 @@ var listSnapshotsResponseInitiativesItemStatusReportsItemBudgetCommentMax = 1e4;
4280
4280
  var listSnapshotsResponseInitiativesItemStatusReportsItemSkillsCommentMax = 1e4;
4281
4281
  var listSnapshotsResponseInitiativesItemStatusReportsItemSummaryMax = 1e4;
4282
4282
  var listSnapshotsResponseInitiativesItemStatusReportsMax = 1e3;
4283
+ var listSnapshotsResponseInitiativesItemMilestonesItemTitleMax = 300;
4284
+ var listSnapshotsResponseInitiativesItemMilestonesItemBaselineDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
4285
+ var listSnapshotsResponseInitiativesItemMilestonesItemForecastDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
4286
+ var listSnapshotsResponseInitiativesItemMilestonesItemDoneDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
4287
+ var listSnapshotsResponseInitiativesItemMilestonesItemNoteMax = 1e4;
4288
+ var listSnapshotsResponseInitiativesItemMilestonesMax = 30;
4289
+ var listSnapshotsResponseInitiativesItemRisksItemTitleMax = 300;
4290
+ var listSnapshotsResponseInitiativesItemRisksItemProbabilityMax = 5;
4291
+ var listSnapshotsResponseInitiativesItemRisksItemImpactMax = 5;
4292
+ var listSnapshotsResponseInitiativesItemRisksItemResidualProbabilityMax = 5;
4293
+ var listSnapshotsResponseInitiativesItemRisksItemResidualImpactMax = 5;
4294
+ var listSnapshotsResponseInitiativesItemRisksItemOwnerMax = 300;
4295
+ var listSnapshotsResponseInitiativesItemRisksItemMitigationMax = 1e4;
4296
+ var listSnapshotsResponseInitiativesItemRisksItemRaisedDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
4297
+ var listSnapshotsResponseInitiativesItemRisksItemReviewDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
4298
+ var listSnapshotsResponseInitiativesItemRisksItemOccurredDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
4299
+ var listSnapshotsResponseInitiativesItemRisksItemNoteMax = 1e4;
4300
+ var listSnapshotsResponseInitiativesItemRisksMax = 50;
4283
4301
  var listSnapshotsResponseInitiativesItemDependsOnMax = 1e3;
4284
4302
  var listSnapshotsResponseInitiativesItemRequiredSkillsItemRunFteMin = 0;
4285
4303
  var listSnapshotsResponseInitiativesItemRequiredSkillsMax = 1e3;
@@ -4481,6 +4499,30 @@ var ListSnapshotsResponseItem = objectType({
4481
4499
  }),
4482
4500
  "summary": stringType().max(listSnapshotsResponseInitiativesItemStatusReportsItemSummaryMax).optional()
4483
4501
  })).max(listSnapshotsResponseInitiativesItemStatusReportsMax).optional(),
4502
+ "milestones": arrayType(objectType({
4503
+ "id": stringType(),
4504
+ "title": stringType().min(1).max(listSnapshotsResponseInitiativesItemMilestonesItemTitleMax),
4505
+ "baselineDate": stringType().regex(listSnapshotsResponseInitiativesItemMilestonesItemBaselineDateRegExp),
4506
+ "forecastDate": stringType().regex(listSnapshotsResponseInitiativesItemMilestonesItemForecastDateRegExp).optional(),
4507
+ "doneDate": stringType().regex(listSnapshotsResponseInitiativesItemMilestonesItemDoneDateRegExp).optional(),
4508
+ "note": stringType().max(listSnapshotsResponseInitiativesItemMilestonesItemNoteMax).optional()
4509
+ }).describe("A dated intermediate result (docs/milestones-concept-2026-10-17.md). baselineDate is the agreed plan, forecastDate today's expectation (absent = the baseline), doneDate marks it reached; all yyyy-mm-dd.")).max(listSnapshotsResponseInitiativesItemMilestonesMax).optional(),
4510
+ "risks": arrayType(objectType({
4511
+ "id": stringType(),
4512
+ "title": stringType().min(1).max(listSnapshotsResponseInitiativesItemRisksItemTitleMax),
4513
+ "category": enumType(["delivery", "vendor", "data", "people", "regulatory", "technical", "financial"]),
4514
+ "probability": numberType().min(1).max(listSnapshotsResponseInitiativesItemRisksItemProbabilityMax),
4515
+ "impact": numberType().min(1).max(listSnapshotsResponseInitiativesItemRisksItemImpactMax),
4516
+ "residualProbability": numberType().min(1).max(listSnapshotsResponseInitiativesItemRisksItemResidualProbabilityMax).optional(),
4517
+ "residualImpact": numberType().min(1).max(listSnapshotsResponseInitiativesItemRisksItemResidualImpactMax).optional(),
4518
+ "status": enumType(["open", "mitigating", "closed", "occurred"]),
4519
+ "owner": stringType().max(listSnapshotsResponseInitiativesItemRisksItemOwnerMax).optional(),
4520
+ "mitigation": stringType().max(listSnapshotsResponseInitiativesItemRisksItemMitigationMax).optional(),
4521
+ "raisedDate": stringType().regex(listSnapshotsResponseInitiativesItemRisksItemRaisedDateRegExp).optional(),
4522
+ "reviewDate": stringType().regex(listSnapshotsResponseInitiativesItemRisksItemReviewDateRegExp).optional(),
4523
+ "occurredDate": stringType().regex(listSnapshotsResponseInitiativesItemRisksItemOccurredDateRegExp).optional(),
4524
+ "note": stringType().max(listSnapshotsResponseInitiativesItemRisksItemNoteMax).optional()
4525
+ }).describe("A concrete project risk, or an issue when status is occurred (docs/risks-issues-follow-ups-concept-2026-10-19.md). Probability and impact are integers 1-5; the residual pair (after mitigation) is sent as a pair or not at all. Dates are yyyy-mm-dd.")).max(listSnapshotsResponseInitiativesItemRisksMax).optional(),
4484
4526
  "dependsOn": arrayType(stringType()).max(listSnapshotsResponseInitiativesItemDependsOnMax),
4485
4527
  "requiredSkills": arrayType(objectType({
4486
4528
  "skillId": stringType(),
@@ -4618,6 +4660,24 @@ var createSnapshotBodyInitiativesItemStatusReportsItemBudgetCommentMax = 1e4;
4618
4660
  var createSnapshotBodyInitiativesItemStatusReportsItemSkillsCommentMax = 1e4;
4619
4661
  var createSnapshotBodyInitiativesItemStatusReportsItemSummaryMax = 1e4;
4620
4662
  var createSnapshotBodyInitiativesItemStatusReportsMax = 1e3;
4663
+ var createSnapshotBodyInitiativesItemMilestonesItemTitleMax = 300;
4664
+ var createSnapshotBodyInitiativesItemMilestonesItemBaselineDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
4665
+ var createSnapshotBodyInitiativesItemMilestonesItemForecastDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
4666
+ var createSnapshotBodyInitiativesItemMilestonesItemDoneDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
4667
+ var createSnapshotBodyInitiativesItemMilestonesItemNoteMax = 1e4;
4668
+ var createSnapshotBodyInitiativesItemMilestonesMax = 30;
4669
+ var createSnapshotBodyInitiativesItemRisksItemTitleMax = 300;
4670
+ var createSnapshotBodyInitiativesItemRisksItemProbabilityMax = 5;
4671
+ var createSnapshotBodyInitiativesItemRisksItemImpactMax = 5;
4672
+ var createSnapshotBodyInitiativesItemRisksItemResidualProbabilityMax = 5;
4673
+ var createSnapshotBodyInitiativesItemRisksItemResidualImpactMax = 5;
4674
+ var createSnapshotBodyInitiativesItemRisksItemOwnerMax = 300;
4675
+ var createSnapshotBodyInitiativesItemRisksItemMitigationMax = 1e4;
4676
+ var createSnapshotBodyInitiativesItemRisksItemRaisedDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
4677
+ var createSnapshotBodyInitiativesItemRisksItemReviewDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
4678
+ var createSnapshotBodyInitiativesItemRisksItemOccurredDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
4679
+ var createSnapshotBodyInitiativesItemRisksItemNoteMax = 1e4;
4680
+ var createSnapshotBodyInitiativesItemRisksMax = 50;
4621
4681
  var createSnapshotBodyInitiativesItemDependsOnMax = 1e3;
4622
4682
  var createSnapshotBodyInitiativesItemRequiredSkillsItemRunFteMin = 0;
4623
4683
  var createSnapshotBodyInitiativesItemRequiredSkillsMax = 1e3;
@@ -4819,6 +4879,30 @@ var CreateSnapshotBody = objectType({
4819
4879
  }),
4820
4880
  "summary": stringType().max(createSnapshotBodyInitiativesItemStatusReportsItemSummaryMax).optional()
4821
4881
  })).max(createSnapshotBodyInitiativesItemStatusReportsMax).optional(),
4882
+ "milestones": arrayType(objectType({
4883
+ "id": stringType(),
4884
+ "title": stringType().min(1).max(createSnapshotBodyInitiativesItemMilestonesItemTitleMax),
4885
+ "baselineDate": stringType().regex(createSnapshotBodyInitiativesItemMilestonesItemBaselineDateRegExp),
4886
+ "forecastDate": stringType().regex(createSnapshotBodyInitiativesItemMilestonesItemForecastDateRegExp).optional(),
4887
+ "doneDate": stringType().regex(createSnapshotBodyInitiativesItemMilestonesItemDoneDateRegExp).optional(),
4888
+ "note": stringType().max(createSnapshotBodyInitiativesItemMilestonesItemNoteMax).optional()
4889
+ }).describe("A dated intermediate result (docs/milestones-concept-2026-10-17.md). baselineDate is the agreed plan, forecastDate today's expectation (absent = the baseline), doneDate marks it reached; all yyyy-mm-dd.")).max(createSnapshotBodyInitiativesItemMilestonesMax).optional(),
4890
+ "risks": arrayType(objectType({
4891
+ "id": stringType(),
4892
+ "title": stringType().min(1).max(createSnapshotBodyInitiativesItemRisksItemTitleMax),
4893
+ "category": enumType(["delivery", "vendor", "data", "people", "regulatory", "technical", "financial"]),
4894
+ "probability": numberType().min(1).max(createSnapshotBodyInitiativesItemRisksItemProbabilityMax),
4895
+ "impact": numberType().min(1).max(createSnapshotBodyInitiativesItemRisksItemImpactMax),
4896
+ "residualProbability": numberType().min(1).max(createSnapshotBodyInitiativesItemRisksItemResidualProbabilityMax).optional(),
4897
+ "residualImpact": numberType().min(1).max(createSnapshotBodyInitiativesItemRisksItemResidualImpactMax).optional(),
4898
+ "status": enumType(["open", "mitigating", "closed", "occurred"]),
4899
+ "owner": stringType().max(createSnapshotBodyInitiativesItemRisksItemOwnerMax).optional(),
4900
+ "mitigation": stringType().max(createSnapshotBodyInitiativesItemRisksItemMitigationMax).optional(),
4901
+ "raisedDate": stringType().regex(createSnapshotBodyInitiativesItemRisksItemRaisedDateRegExp).optional(),
4902
+ "reviewDate": stringType().regex(createSnapshotBodyInitiativesItemRisksItemReviewDateRegExp).optional(),
4903
+ "occurredDate": stringType().regex(createSnapshotBodyInitiativesItemRisksItemOccurredDateRegExp).optional(),
4904
+ "note": stringType().max(createSnapshotBodyInitiativesItemRisksItemNoteMax).optional()
4905
+ }).describe("A concrete project risk, or an issue when status is occurred (docs/risks-issues-follow-ups-concept-2026-10-19.md). Probability and impact are integers 1-5; the residual pair (after mitigation) is sent as a pair or not at all. Dates are yyyy-mm-dd.")).max(createSnapshotBodyInitiativesItemRisksMax).optional(),
4822
4906
  "dependsOn": arrayType(stringType()).max(createSnapshotBodyInitiativesItemDependsOnMax),
4823
4907
  "requiredSkills": arrayType(objectType({
4824
4908
  "skillId": stringType(),
@@ -4962,6 +5046,24 @@ var renameSnapshotResponseInitiativesItemStatusReportsItemBudgetCommentMax = 1e4
4962
5046
  var renameSnapshotResponseInitiativesItemStatusReportsItemSkillsCommentMax = 1e4;
4963
5047
  var renameSnapshotResponseInitiativesItemStatusReportsItemSummaryMax = 1e4;
4964
5048
  var renameSnapshotResponseInitiativesItemStatusReportsMax = 1e3;
5049
+ var renameSnapshotResponseInitiativesItemMilestonesItemTitleMax = 300;
5050
+ var renameSnapshotResponseInitiativesItemMilestonesItemBaselineDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
5051
+ var renameSnapshotResponseInitiativesItemMilestonesItemForecastDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
5052
+ var renameSnapshotResponseInitiativesItemMilestonesItemDoneDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
5053
+ var renameSnapshotResponseInitiativesItemMilestonesItemNoteMax = 1e4;
5054
+ var renameSnapshotResponseInitiativesItemMilestonesMax = 30;
5055
+ var renameSnapshotResponseInitiativesItemRisksItemTitleMax = 300;
5056
+ var renameSnapshotResponseInitiativesItemRisksItemProbabilityMax = 5;
5057
+ var renameSnapshotResponseInitiativesItemRisksItemImpactMax = 5;
5058
+ var renameSnapshotResponseInitiativesItemRisksItemResidualProbabilityMax = 5;
5059
+ var renameSnapshotResponseInitiativesItemRisksItemResidualImpactMax = 5;
5060
+ var renameSnapshotResponseInitiativesItemRisksItemOwnerMax = 300;
5061
+ var renameSnapshotResponseInitiativesItemRisksItemMitigationMax = 1e4;
5062
+ var renameSnapshotResponseInitiativesItemRisksItemRaisedDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
5063
+ var renameSnapshotResponseInitiativesItemRisksItemReviewDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
5064
+ var renameSnapshotResponseInitiativesItemRisksItemOccurredDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
5065
+ var renameSnapshotResponseInitiativesItemRisksItemNoteMax = 1e4;
5066
+ var renameSnapshotResponseInitiativesItemRisksMax = 50;
4965
5067
  var renameSnapshotResponseInitiativesItemDependsOnMax = 1e3;
4966
5068
  var renameSnapshotResponseInitiativesItemRequiredSkillsItemRunFteMin = 0;
4967
5069
  var renameSnapshotResponseInitiativesItemRequiredSkillsMax = 1e3;
@@ -5163,6 +5265,30 @@ var RenameSnapshotResponse = objectType({
5163
5265
  }),
5164
5266
  "summary": stringType().max(renameSnapshotResponseInitiativesItemStatusReportsItemSummaryMax).optional()
5165
5267
  })).max(renameSnapshotResponseInitiativesItemStatusReportsMax).optional(),
5268
+ "milestones": arrayType(objectType({
5269
+ "id": stringType(),
5270
+ "title": stringType().min(1).max(renameSnapshotResponseInitiativesItemMilestonesItemTitleMax),
5271
+ "baselineDate": stringType().regex(renameSnapshotResponseInitiativesItemMilestonesItemBaselineDateRegExp),
5272
+ "forecastDate": stringType().regex(renameSnapshotResponseInitiativesItemMilestonesItemForecastDateRegExp).optional(),
5273
+ "doneDate": stringType().regex(renameSnapshotResponseInitiativesItemMilestonesItemDoneDateRegExp).optional(),
5274
+ "note": stringType().max(renameSnapshotResponseInitiativesItemMilestonesItemNoteMax).optional()
5275
+ }).describe("A dated intermediate result (docs/milestones-concept-2026-10-17.md). baselineDate is the agreed plan, forecastDate today's expectation (absent = the baseline), doneDate marks it reached; all yyyy-mm-dd.")).max(renameSnapshotResponseInitiativesItemMilestonesMax).optional(),
5276
+ "risks": arrayType(objectType({
5277
+ "id": stringType(),
5278
+ "title": stringType().min(1).max(renameSnapshotResponseInitiativesItemRisksItemTitleMax),
5279
+ "category": enumType(["delivery", "vendor", "data", "people", "regulatory", "technical", "financial"]),
5280
+ "probability": numberType().min(1).max(renameSnapshotResponseInitiativesItemRisksItemProbabilityMax),
5281
+ "impact": numberType().min(1).max(renameSnapshotResponseInitiativesItemRisksItemImpactMax),
5282
+ "residualProbability": numberType().min(1).max(renameSnapshotResponseInitiativesItemRisksItemResidualProbabilityMax).optional(),
5283
+ "residualImpact": numberType().min(1).max(renameSnapshotResponseInitiativesItemRisksItemResidualImpactMax).optional(),
5284
+ "status": enumType(["open", "mitigating", "closed", "occurred"]),
5285
+ "owner": stringType().max(renameSnapshotResponseInitiativesItemRisksItemOwnerMax).optional(),
5286
+ "mitigation": stringType().max(renameSnapshotResponseInitiativesItemRisksItemMitigationMax).optional(),
5287
+ "raisedDate": stringType().regex(renameSnapshotResponseInitiativesItemRisksItemRaisedDateRegExp).optional(),
5288
+ "reviewDate": stringType().regex(renameSnapshotResponseInitiativesItemRisksItemReviewDateRegExp).optional(),
5289
+ "occurredDate": stringType().regex(renameSnapshotResponseInitiativesItemRisksItemOccurredDateRegExp).optional(),
5290
+ "note": stringType().max(renameSnapshotResponseInitiativesItemRisksItemNoteMax).optional()
5291
+ }).describe("A concrete project risk, or an issue when status is occurred (docs/risks-issues-follow-ups-concept-2026-10-19.md). Probability and impact are integers 1-5; the residual pair (after mitigation) is sent as a pair or not at all. Dates are yyyy-mm-dd.")).max(renameSnapshotResponseInitiativesItemRisksMax).optional(),
5166
5292
  "dependsOn": arrayType(stringType()).max(renameSnapshotResponseInitiativesItemDependsOnMax),
5167
5293
  "requiredSkills": arrayType(objectType({
5168
5294
  "skillId": stringType(),
@@ -5301,6 +5427,24 @@ var listInitiativesResponseStatusReportsItemBudgetCommentMax = 1e4;
5301
5427
  var listInitiativesResponseStatusReportsItemSkillsCommentMax = 1e4;
5302
5428
  var listInitiativesResponseStatusReportsItemSummaryMax = 1e4;
5303
5429
  var listInitiativesResponseStatusReportsMax = 1e3;
5430
+ var listInitiativesResponseMilestonesItemTitleMax = 300;
5431
+ var listInitiativesResponseMilestonesItemBaselineDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
5432
+ var listInitiativesResponseMilestonesItemForecastDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
5433
+ var listInitiativesResponseMilestonesItemDoneDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
5434
+ var listInitiativesResponseMilestonesItemNoteMax = 1e4;
5435
+ var listInitiativesResponseMilestonesMax = 30;
5436
+ var listInitiativesResponseRisksItemTitleMax = 300;
5437
+ var listInitiativesResponseRisksItemProbabilityMax = 5;
5438
+ var listInitiativesResponseRisksItemImpactMax = 5;
5439
+ var listInitiativesResponseRisksItemResidualProbabilityMax = 5;
5440
+ var listInitiativesResponseRisksItemResidualImpactMax = 5;
5441
+ var listInitiativesResponseRisksItemOwnerMax = 300;
5442
+ var listInitiativesResponseRisksItemMitigationMax = 1e4;
5443
+ var listInitiativesResponseRisksItemRaisedDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
5444
+ var listInitiativesResponseRisksItemReviewDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
5445
+ var listInitiativesResponseRisksItemOccurredDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
5446
+ var listInitiativesResponseRisksItemNoteMax = 1e4;
5447
+ var listInitiativesResponseRisksMax = 50;
5304
5448
  var listInitiativesResponseDependsOnMax = 1e3;
5305
5449
  var listInitiativesResponseRequiredSkillsItemRunFteMin = 0;
5306
5450
  var listInitiativesResponseRequiredSkillsMax = 1e3;
@@ -5496,6 +5640,30 @@ var ListInitiativesResponseItem = objectType({
5496
5640
  }),
5497
5641
  "summary": stringType().max(listInitiativesResponseStatusReportsItemSummaryMax).optional()
5498
5642
  })).max(listInitiativesResponseStatusReportsMax).optional(),
5643
+ "milestones": arrayType(objectType({
5644
+ "id": stringType(),
5645
+ "title": stringType().min(1).max(listInitiativesResponseMilestonesItemTitleMax),
5646
+ "baselineDate": stringType().regex(listInitiativesResponseMilestonesItemBaselineDateRegExp),
5647
+ "forecastDate": stringType().regex(listInitiativesResponseMilestonesItemForecastDateRegExp).optional(),
5648
+ "doneDate": stringType().regex(listInitiativesResponseMilestonesItemDoneDateRegExp).optional(),
5649
+ "note": stringType().max(listInitiativesResponseMilestonesItemNoteMax).optional()
5650
+ }).describe("A dated intermediate result (docs/milestones-concept-2026-10-17.md). baselineDate is the agreed plan, forecastDate today's expectation (absent = the baseline), doneDate marks it reached; all yyyy-mm-dd.")).max(listInitiativesResponseMilestonesMax).optional(),
5651
+ "risks": arrayType(objectType({
5652
+ "id": stringType(),
5653
+ "title": stringType().min(1).max(listInitiativesResponseRisksItemTitleMax),
5654
+ "category": enumType(["delivery", "vendor", "data", "people", "regulatory", "technical", "financial"]),
5655
+ "probability": numberType().min(1).max(listInitiativesResponseRisksItemProbabilityMax),
5656
+ "impact": numberType().min(1).max(listInitiativesResponseRisksItemImpactMax),
5657
+ "residualProbability": numberType().min(1).max(listInitiativesResponseRisksItemResidualProbabilityMax).optional(),
5658
+ "residualImpact": numberType().min(1).max(listInitiativesResponseRisksItemResidualImpactMax).optional(),
5659
+ "status": enumType(["open", "mitigating", "closed", "occurred"]),
5660
+ "owner": stringType().max(listInitiativesResponseRisksItemOwnerMax).optional(),
5661
+ "mitigation": stringType().max(listInitiativesResponseRisksItemMitigationMax).optional(),
5662
+ "raisedDate": stringType().regex(listInitiativesResponseRisksItemRaisedDateRegExp).optional(),
5663
+ "reviewDate": stringType().regex(listInitiativesResponseRisksItemReviewDateRegExp).optional(),
5664
+ "occurredDate": stringType().regex(listInitiativesResponseRisksItemOccurredDateRegExp).optional(),
5665
+ "note": stringType().max(listInitiativesResponseRisksItemNoteMax).optional()
5666
+ }).describe("A concrete project risk, or an issue when status is occurred (docs/risks-issues-follow-ups-concept-2026-10-19.md). Probability and impact are integers 1-5; the residual pair (after mitigation) is sent as a pair or not at all. Dates are yyyy-mm-dd.")).max(listInitiativesResponseRisksMax).optional(),
5499
5667
  "dependsOn": arrayType(stringType()).max(listInitiativesResponseDependsOnMax),
5500
5668
  "requiredSkills": arrayType(objectType({
5501
5669
  "skillId": stringType(),
@@ -5630,6 +5798,24 @@ var createInitiativeBodyOneStatusReportsItemBudgetCommentMax = 1e4;
5630
5798
  var createInitiativeBodyOneStatusReportsItemSkillsCommentMax = 1e4;
5631
5799
  var createInitiativeBodyOneStatusReportsItemSummaryMax = 1e4;
5632
5800
  var createInitiativeBodyOneStatusReportsMax = 1e3;
5801
+ var createInitiativeBodyOneMilestonesItemTitleMax = 300;
5802
+ var createInitiativeBodyOneMilestonesItemBaselineDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
5803
+ var createInitiativeBodyOneMilestonesItemForecastDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
5804
+ var createInitiativeBodyOneMilestonesItemDoneDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
5805
+ var createInitiativeBodyOneMilestonesItemNoteMax = 1e4;
5806
+ var createInitiativeBodyOneMilestonesMax = 30;
5807
+ var createInitiativeBodyOneRisksItemTitleMax = 300;
5808
+ var createInitiativeBodyOneRisksItemProbabilityMax = 5;
5809
+ var createInitiativeBodyOneRisksItemImpactMax = 5;
5810
+ var createInitiativeBodyOneRisksItemResidualProbabilityMax = 5;
5811
+ var createInitiativeBodyOneRisksItemResidualImpactMax = 5;
5812
+ var createInitiativeBodyOneRisksItemOwnerMax = 300;
5813
+ var createInitiativeBodyOneRisksItemMitigationMax = 1e4;
5814
+ var createInitiativeBodyOneRisksItemRaisedDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
5815
+ var createInitiativeBodyOneRisksItemReviewDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
5816
+ var createInitiativeBodyOneRisksItemOccurredDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
5817
+ var createInitiativeBodyOneRisksItemNoteMax = 1e4;
5818
+ var createInitiativeBodyOneRisksMax = 50;
5633
5819
  var createInitiativeBodyOneDependsOnMax = 1e3;
5634
5820
  var createInitiativeBodyOneRequiredSkillsItemRunFteMin = 0;
5635
5821
  var createInitiativeBodyOneRequiredSkillsMax = 1e3;
@@ -5825,6 +6011,30 @@ var CreateInitiativeBody = objectType({
5825
6011
  }),
5826
6012
  "summary": stringType().max(createInitiativeBodyOneStatusReportsItemSummaryMax).optional()
5827
6013
  })).max(createInitiativeBodyOneStatusReportsMax).optional(),
6014
+ "milestones": arrayType(objectType({
6015
+ "id": stringType(),
6016
+ "title": stringType().min(1).max(createInitiativeBodyOneMilestonesItemTitleMax),
6017
+ "baselineDate": stringType().regex(createInitiativeBodyOneMilestonesItemBaselineDateRegExp),
6018
+ "forecastDate": stringType().regex(createInitiativeBodyOneMilestonesItemForecastDateRegExp).optional(),
6019
+ "doneDate": stringType().regex(createInitiativeBodyOneMilestonesItemDoneDateRegExp).optional(),
6020
+ "note": stringType().max(createInitiativeBodyOneMilestonesItemNoteMax).optional()
6021
+ }).describe("A dated intermediate result (docs/milestones-concept-2026-10-17.md). baselineDate is the agreed plan, forecastDate today's expectation (absent = the baseline), doneDate marks it reached; all yyyy-mm-dd.")).max(createInitiativeBodyOneMilestonesMax).optional(),
6022
+ "risks": arrayType(objectType({
6023
+ "id": stringType(),
6024
+ "title": stringType().min(1).max(createInitiativeBodyOneRisksItemTitleMax),
6025
+ "category": enumType(["delivery", "vendor", "data", "people", "regulatory", "technical", "financial"]),
6026
+ "probability": numberType().min(1).max(createInitiativeBodyOneRisksItemProbabilityMax),
6027
+ "impact": numberType().min(1).max(createInitiativeBodyOneRisksItemImpactMax),
6028
+ "residualProbability": numberType().min(1).max(createInitiativeBodyOneRisksItemResidualProbabilityMax).optional(),
6029
+ "residualImpact": numberType().min(1).max(createInitiativeBodyOneRisksItemResidualImpactMax).optional(),
6030
+ "status": enumType(["open", "mitigating", "closed", "occurred"]),
6031
+ "owner": stringType().max(createInitiativeBodyOneRisksItemOwnerMax).optional(),
6032
+ "mitigation": stringType().max(createInitiativeBodyOneRisksItemMitigationMax).optional(),
6033
+ "raisedDate": stringType().regex(createInitiativeBodyOneRisksItemRaisedDateRegExp).optional(),
6034
+ "reviewDate": stringType().regex(createInitiativeBodyOneRisksItemReviewDateRegExp).optional(),
6035
+ "occurredDate": stringType().regex(createInitiativeBodyOneRisksItemOccurredDateRegExp).optional(),
6036
+ "note": stringType().max(createInitiativeBodyOneRisksItemNoteMax).optional()
6037
+ }).describe("A concrete project risk, or an issue when status is occurred (docs/risks-issues-follow-ups-concept-2026-10-19.md). Probability and impact are integers 1-5; the residual pair (after mitigation) is sent as a pair or not at all. Dates are yyyy-mm-dd.")).max(createInitiativeBodyOneRisksMax).optional(),
5828
6038
  "dependsOn": arrayType(stringType()).max(createInitiativeBodyOneDependsOnMax),
5829
6039
  "requiredSkills": arrayType(objectType({
5830
6040
  "skillId": stringType(),
@@ -5969,6 +6179,24 @@ var getInitiativeResponseStatusReportsItemBudgetCommentMax = 1e4;
5969
6179
  var getInitiativeResponseStatusReportsItemSkillsCommentMax = 1e4;
5970
6180
  var getInitiativeResponseStatusReportsItemSummaryMax = 1e4;
5971
6181
  var getInitiativeResponseStatusReportsMax = 1e3;
6182
+ var getInitiativeResponseMilestonesItemTitleMax = 300;
6183
+ var getInitiativeResponseMilestonesItemBaselineDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
6184
+ var getInitiativeResponseMilestonesItemForecastDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
6185
+ var getInitiativeResponseMilestonesItemDoneDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
6186
+ var getInitiativeResponseMilestonesItemNoteMax = 1e4;
6187
+ var getInitiativeResponseMilestonesMax = 30;
6188
+ var getInitiativeResponseRisksItemTitleMax = 300;
6189
+ var getInitiativeResponseRisksItemProbabilityMax = 5;
6190
+ var getInitiativeResponseRisksItemImpactMax = 5;
6191
+ var getInitiativeResponseRisksItemResidualProbabilityMax = 5;
6192
+ var getInitiativeResponseRisksItemResidualImpactMax = 5;
6193
+ var getInitiativeResponseRisksItemOwnerMax = 300;
6194
+ var getInitiativeResponseRisksItemMitigationMax = 1e4;
6195
+ var getInitiativeResponseRisksItemRaisedDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
6196
+ var getInitiativeResponseRisksItemReviewDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
6197
+ var getInitiativeResponseRisksItemOccurredDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
6198
+ var getInitiativeResponseRisksItemNoteMax = 1e4;
6199
+ var getInitiativeResponseRisksMax = 50;
5972
6200
  var getInitiativeResponseDependsOnMax = 1e3;
5973
6201
  var getInitiativeResponseRequiredSkillsItemRunFteMin = 0;
5974
6202
  var getInitiativeResponseRequiredSkillsMax = 1e3;
@@ -6164,6 +6392,30 @@ var GetInitiativeResponse = objectType({
6164
6392
  }),
6165
6393
  "summary": stringType().max(getInitiativeResponseStatusReportsItemSummaryMax).optional()
6166
6394
  })).max(getInitiativeResponseStatusReportsMax).optional(),
6395
+ "milestones": arrayType(objectType({
6396
+ "id": stringType(),
6397
+ "title": stringType().min(1).max(getInitiativeResponseMilestonesItemTitleMax),
6398
+ "baselineDate": stringType().regex(getInitiativeResponseMilestonesItemBaselineDateRegExp),
6399
+ "forecastDate": stringType().regex(getInitiativeResponseMilestonesItemForecastDateRegExp).optional(),
6400
+ "doneDate": stringType().regex(getInitiativeResponseMilestonesItemDoneDateRegExp).optional(),
6401
+ "note": stringType().max(getInitiativeResponseMilestonesItemNoteMax).optional()
6402
+ }).describe("A dated intermediate result (docs/milestones-concept-2026-10-17.md). baselineDate is the agreed plan, forecastDate today's expectation (absent = the baseline), doneDate marks it reached; all yyyy-mm-dd.")).max(getInitiativeResponseMilestonesMax).optional(),
6403
+ "risks": arrayType(objectType({
6404
+ "id": stringType(),
6405
+ "title": stringType().min(1).max(getInitiativeResponseRisksItemTitleMax),
6406
+ "category": enumType(["delivery", "vendor", "data", "people", "regulatory", "technical", "financial"]),
6407
+ "probability": numberType().min(1).max(getInitiativeResponseRisksItemProbabilityMax),
6408
+ "impact": numberType().min(1).max(getInitiativeResponseRisksItemImpactMax),
6409
+ "residualProbability": numberType().min(1).max(getInitiativeResponseRisksItemResidualProbabilityMax).optional(),
6410
+ "residualImpact": numberType().min(1).max(getInitiativeResponseRisksItemResidualImpactMax).optional(),
6411
+ "status": enumType(["open", "mitigating", "closed", "occurred"]),
6412
+ "owner": stringType().max(getInitiativeResponseRisksItemOwnerMax).optional(),
6413
+ "mitigation": stringType().max(getInitiativeResponseRisksItemMitigationMax).optional(),
6414
+ "raisedDate": stringType().regex(getInitiativeResponseRisksItemRaisedDateRegExp).optional(),
6415
+ "reviewDate": stringType().regex(getInitiativeResponseRisksItemReviewDateRegExp).optional(),
6416
+ "occurredDate": stringType().regex(getInitiativeResponseRisksItemOccurredDateRegExp).optional(),
6417
+ "note": stringType().max(getInitiativeResponseRisksItemNoteMax).optional()
6418
+ }).describe("A concrete project risk, or an issue when status is occurred (docs/risks-issues-follow-ups-concept-2026-10-19.md). Probability and impact are integers 1-5; the residual pair (after mitigation) is sent as a pair or not at all. Dates are yyyy-mm-dd.")).max(getInitiativeResponseRisksMax).optional(),
6167
6419
  "dependsOn": arrayType(stringType()).max(getInitiativeResponseDependsOnMax),
6168
6420
  "requiredSkills": arrayType(objectType({
6169
6421
  "skillId": stringType(),
@@ -6300,6 +6552,24 @@ var updateInitiativeBodyOneStatusReportsItemBudgetCommentMax = 1e4;
6300
6552
  var updateInitiativeBodyOneStatusReportsItemSkillsCommentMax = 1e4;
6301
6553
  var updateInitiativeBodyOneStatusReportsItemSummaryMax = 1e4;
6302
6554
  var updateInitiativeBodyOneStatusReportsMax = 1e3;
6555
+ var updateInitiativeBodyOneMilestonesItemTitleMax = 300;
6556
+ var updateInitiativeBodyOneMilestonesItemBaselineDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
6557
+ var updateInitiativeBodyOneMilestonesItemForecastDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
6558
+ var updateInitiativeBodyOneMilestonesItemDoneDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
6559
+ var updateInitiativeBodyOneMilestonesItemNoteMax = 1e4;
6560
+ var updateInitiativeBodyOneMilestonesMax = 30;
6561
+ var updateInitiativeBodyOneRisksItemTitleMax = 300;
6562
+ var updateInitiativeBodyOneRisksItemProbabilityMax = 5;
6563
+ var updateInitiativeBodyOneRisksItemImpactMax = 5;
6564
+ var updateInitiativeBodyOneRisksItemResidualProbabilityMax = 5;
6565
+ var updateInitiativeBodyOneRisksItemResidualImpactMax = 5;
6566
+ var updateInitiativeBodyOneRisksItemOwnerMax = 300;
6567
+ var updateInitiativeBodyOneRisksItemMitigationMax = 1e4;
6568
+ var updateInitiativeBodyOneRisksItemRaisedDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
6569
+ var updateInitiativeBodyOneRisksItemReviewDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
6570
+ var updateInitiativeBodyOneRisksItemOccurredDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
6571
+ var updateInitiativeBodyOneRisksItemNoteMax = 1e4;
6572
+ var updateInitiativeBodyOneRisksMax = 50;
6303
6573
  var updateInitiativeBodyOneDependsOnMax = 1e3;
6304
6574
  var updateInitiativeBodyOneRequiredSkillsItemRunFteMin = 0;
6305
6575
  var updateInitiativeBodyOneRequiredSkillsMax = 1e3;
@@ -6495,6 +6765,30 @@ var UpdateInitiativeBody = objectType({
6495
6765
  }),
6496
6766
  "summary": stringType().max(updateInitiativeBodyOneStatusReportsItemSummaryMax).optional()
6497
6767
  })).max(updateInitiativeBodyOneStatusReportsMax).optional(),
6768
+ "milestones": arrayType(objectType({
6769
+ "id": stringType(),
6770
+ "title": stringType().min(1).max(updateInitiativeBodyOneMilestonesItemTitleMax),
6771
+ "baselineDate": stringType().regex(updateInitiativeBodyOneMilestonesItemBaselineDateRegExp),
6772
+ "forecastDate": stringType().regex(updateInitiativeBodyOneMilestonesItemForecastDateRegExp).optional(),
6773
+ "doneDate": stringType().regex(updateInitiativeBodyOneMilestonesItemDoneDateRegExp).optional(),
6774
+ "note": stringType().max(updateInitiativeBodyOneMilestonesItemNoteMax).optional()
6775
+ }).describe("A dated intermediate result (docs/milestones-concept-2026-10-17.md). baselineDate is the agreed plan, forecastDate today's expectation (absent = the baseline), doneDate marks it reached; all yyyy-mm-dd.")).max(updateInitiativeBodyOneMilestonesMax).optional(),
6776
+ "risks": arrayType(objectType({
6777
+ "id": stringType(),
6778
+ "title": stringType().min(1).max(updateInitiativeBodyOneRisksItemTitleMax),
6779
+ "category": enumType(["delivery", "vendor", "data", "people", "regulatory", "technical", "financial"]),
6780
+ "probability": numberType().min(1).max(updateInitiativeBodyOneRisksItemProbabilityMax),
6781
+ "impact": numberType().min(1).max(updateInitiativeBodyOneRisksItemImpactMax),
6782
+ "residualProbability": numberType().min(1).max(updateInitiativeBodyOneRisksItemResidualProbabilityMax).optional(),
6783
+ "residualImpact": numberType().min(1).max(updateInitiativeBodyOneRisksItemResidualImpactMax).optional(),
6784
+ "status": enumType(["open", "mitigating", "closed", "occurred"]),
6785
+ "owner": stringType().max(updateInitiativeBodyOneRisksItemOwnerMax).optional(),
6786
+ "mitigation": stringType().max(updateInitiativeBodyOneRisksItemMitigationMax).optional(),
6787
+ "raisedDate": stringType().regex(updateInitiativeBodyOneRisksItemRaisedDateRegExp).optional(),
6788
+ "reviewDate": stringType().regex(updateInitiativeBodyOneRisksItemReviewDateRegExp).optional(),
6789
+ "occurredDate": stringType().regex(updateInitiativeBodyOneRisksItemOccurredDateRegExp).optional(),
6790
+ "note": stringType().max(updateInitiativeBodyOneRisksItemNoteMax).optional()
6791
+ }).describe("A concrete project risk, or an issue when status is occurred (docs/risks-issues-follow-ups-concept-2026-10-19.md). Probability and impact are integers 1-5; the residual pair (after mitigation) is sent as a pair or not at all. Dates are yyyy-mm-dd.")).max(updateInitiativeBodyOneRisksMax).optional(),
6498
6792
  "dependsOn": arrayType(stringType()).max(updateInitiativeBodyOneDependsOnMax),
6499
6793
  "requiredSkills": arrayType(objectType({
6500
6794
  "skillId": stringType(),
@@ -6636,6 +6930,24 @@ var updateInitiativeResponseStatusReportsItemBudgetCommentMax = 1e4;
6636
6930
  var updateInitiativeResponseStatusReportsItemSkillsCommentMax = 1e4;
6637
6931
  var updateInitiativeResponseStatusReportsItemSummaryMax = 1e4;
6638
6932
  var updateInitiativeResponseStatusReportsMax = 1e3;
6933
+ var updateInitiativeResponseMilestonesItemTitleMax = 300;
6934
+ var updateInitiativeResponseMilestonesItemBaselineDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
6935
+ var updateInitiativeResponseMilestonesItemForecastDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
6936
+ var updateInitiativeResponseMilestonesItemDoneDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
6937
+ var updateInitiativeResponseMilestonesItemNoteMax = 1e4;
6938
+ var updateInitiativeResponseMilestonesMax = 30;
6939
+ var updateInitiativeResponseRisksItemTitleMax = 300;
6940
+ var updateInitiativeResponseRisksItemProbabilityMax = 5;
6941
+ var updateInitiativeResponseRisksItemImpactMax = 5;
6942
+ var updateInitiativeResponseRisksItemResidualProbabilityMax = 5;
6943
+ var updateInitiativeResponseRisksItemResidualImpactMax = 5;
6944
+ var updateInitiativeResponseRisksItemOwnerMax = 300;
6945
+ var updateInitiativeResponseRisksItemMitigationMax = 1e4;
6946
+ var updateInitiativeResponseRisksItemRaisedDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
6947
+ var updateInitiativeResponseRisksItemReviewDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
6948
+ var updateInitiativeResponseRisksItemOccurredDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
6949
+ var updateInitiativeResponseRisksItemNoteMax = 1e4;
6950
+ var updateInitiativeResponseRisksMax = 50;
6639
6951
  var updateInitiativeResponseDependsOnMax = 1e3;
6640
6952
  var updateInitiativeResponseRequiredSkillsItemRunFteMin = 0;
6641
6953
  var updateInitiativeResponseRequiredSkillsMax = 1e3;
@@ -6831,6 +7143,30 @@ var UpdateInitiativeResponse = objectType({
6831
7143
  }),
6832
7144
  "summary": stringType().max(updateInitiativeResponseStatusReportsItemSummaryMax).optional()
6833
7145
  })).max(updateInitiativeResponseStatusReportsMax).optional(),
7146
+ "milestones": arrayType(objectType({
7147
+ "id": stringType(),
7148
+ "title": stringType().min(1).max(updateInitiativeResponseMilestonesItemTitleMax),
7149
+ "baselineDate": stringType().regex(updateInitiativeResponseMilestonesItemBaselineDateRegExp),
7150
+ "forecastDate": stringType().regex(updateInitiativeResponseMilestonesItemForecastDateRegExp).optional(),
7151
+ "doneDate": stringType().regex(updateInitiativeResponseMilestonesItemDoneDateRegExp).optional(),
7152
+ "note": stringType().max(updateInitiativeResponseMilestonesItemNoteMax).optional()
7153
+ }).describe("A dated intermediate result (docs/milestones-concept-2026-10-17.md). baselineDate is the agreed plan, forecastDate today's expectation (absent = the baseline), doneDate marks it reached; all yyyy-mm-dd.")).max(updateInitiativeResponseMilestonesMax).optional(),
7154
+ "risks": arrayType(objectType({
7155
+ "id": stringType(),
7156
+ "title": stringType().min(1).max(updateInitiativeResponseRisksItemTitleMax),
7157
+ "category": enumType(["delivery", "vendor", "data", "people", "regulatory", "technical", "financial"]),
7158
+ "probability": numberType().min(1).max(updateInitiativeResponseRisksItemProbabilityMax),
7159
+ "impact": numberType().min(1).max(updateInitiativeResponseRisksItemImpactMax),
7160
+ "residualProbability": numberType().min(1).max(updateInitiativeResponseRisksItemResidualProbabilityMax).optional(),
7161
+ "residualImpact": numberType().min(1).max(updateInitiativeResponseRisksItemResidualImpactMax).optional(),
7162
+ "status": enumType(["open", "mitigating", "closed", "occurred"]),
7163
+ "owner": stringType().max(updateInitiativeResponseRisksItemOwnerMax).optional(),
7164
+ "mitigation": stringType().max(updateInitiativeResponseRisksItemMitigationMax).optional(),
7165
+ "raisedDate": stringType().regex(updateInitiativeResponseRisksItemRaisedDateRegExp).optional(),
7166
+ "reviewDate": stringType().regex(updateInitiativeResponseRisksItemReviewDateRegExp).optional(),
7167
+ "occurredDate": stringType().regex(updateInitiativeResponseRisksItemOccurredDateRegExp).optional(),
7168
+ "note": stringType().max(updateInitiativeResponseRisksItemNoteMax).optional()
7169
+ }).describe("A concrete project risk, or an issue when status is occurred (docs/risks-issues-follow-ups-concept-2026-10-19.md). Probability and impact are integers 1-5; the residual pair (after mitigation) is sent as a pair or not at all. Dates are yyyy-mm-dd.")).max(updateInitiativeResponseRisksMax).optional(),
6834
7170
  "dependsOn": arrayType(stringType()).max(updateInitiativeResponseDependsOnMax),
6835
7171
  "requiredSkills": arrayType(objectType({
6836
7172
  "skillId": stringType(),
@@ -9434,6 +9770,13 @@ var OPTIONAL_SECTIONS = [
9434
9770
  { key: "economics", hint: { en: "Benefit/cost P10/P50/P90 ranges, ramp, confidence, discount rate", de: "Nutzen/Kosten P10/P50/P90, Ramp, Konfidenz, Diskontsatz" } },
9435
9771
  { key: "decisionLog", hint: { en: "Dated decisions (go/pause/stop/rescope/rebudget/other)", de: "Datierte Entscheidungen" } },
9436
9772
  { key: "statusReports", hint: { en: "Dated RAG reports (scope/timeline/budget/skills)", de: "Datierte RAG-Berichte" } },
9773
+ {
9774
+ key: "milestones",
9775
+ hint: {
9776
+ en: "[{title, baselineDate, forecastDate?, doneDate?, note?}] \u2014 dated intermediate results (pilot live, vendor selected, go-live; at most 30, title up to 300 characters). baselineDate is the agreed plan; forecastDate today's expectation when it differs; doneDate once reached. Ask for the 3\u20135 that the steering committee watches. On an update, send every milestone the initiative keeps: the file replaces the list.",
9777
+ de: "[{title, baselineDate, forecastDate?, doneDate?, note?}] \u2014 datierte Zwischenergebnisse (Pilot live, Anbieter gew\xE4hlt, Go-live; h\xF6chstens 30, Titel bis 300 Zeichen). baselineDate ist der vereinbarte Plan, forecastDate die heutige Erwartung, wenn sie abweicht, doneDate sobald erreicht. Nach den 3\u20135 fragen, die der Lenkungsausschuss verfolgt. Bei einem Update alle Meilensteine senden, die bleiben sollen: die Datei ersetzt die Liste."
9778
+ }
9779
+ },
9437
9780
  {
9438
9781
  key: "capabilityImpacts",
9439
9782
  hint: {
@@ -9493,7 +9836,7 @@ function describeZodShape(schema, depth = 0) {
9493
9836
  }
9494
9837
  function buildSchemaDescriptor(sectionShapes) {
9495
9838
  return {
9496
- about: "BICon initiative composer. Collect the required fields, then rate every sub-dimension 0\u2013100 (higher = more of the named quality) and a confidence per dimension. Dimension scores are DERIVED (mean of subs) \u2014 never ask the user for them. Values are used verbatim; enum values must match exactly; unknown keys are rejected. Dates: talk dd/mm/yyyy with the user (dd/mm/yyyy, dd.mm.yyyy and yyyy-mm-dd are all accepted; stored as yyyy-mm-dd). Row ids of decision-log entries, status reports and incidents are minted by the Composer \u2014 never invent ids. To UPDATE an existing initiative pass its id as `id`; omit it for a new one.",
9839
+ about: "BICon initiative composer. Collect the required fields, then rate every sub-dimension 0\u2013100 (higher = more of the named quality) and a confidence per dimension. Dimension scores are DERIVED (mean of subs) \u2014 never ask the user for them. Values are used verbatim; enum values must match exactly; unknown keys are rejected. Dates: talk dd/mm/yyyy with the user (dd/mm/yyyy, dd.mm.yyyy and yyyy-mm-dd are all accepted; stored as yyyy-mm-dd). Row ids of decision-log entries, status reports, milestones and incidents are minted by the Composer \u2014 never invent ids. To UPDATE an existing initiative pass its id as `id`; omit it for a new one.",
9497
9840
  requiredFields: REQUIRED_FIELDS,
9498
9841
  enums: {
9499
9842
  status: STATUS_VALUES,
@@ -9525,7 +9868,7 @@ function buildSchemaDescriptor(sectionShapes) {
9525
9868
  },
9526
9869
  optionalSections: OPTIONAL_SECTIONS,
9527
9870
  // Exact shapes of the object/array sections (aiAct, economics, actuals,
9528
- // decisionLog, statusReports, requiredSkills, capabilityImpacts). Keys ending in "?" are
9871
+ // decisionLog, statusReports, requiredSkills, capabilityImpacts, milestones). Keys ending in "?" are
9529
9872
  // optional; "enum[a|b]" lists the allowed values; "<key>" marks a map.
9530
9873
  // Pass these sections as JSON objects/arrays. Any key not listed is
9531
9874
  // rejected with its path.
@@ -9621,7 +9964,7 @@ var parseIfString = (v) => typeof v === "string" ? tryParseJson(v) : v;
9621
9964
  function wireSection(inner, description) {
9622
9965
  return external_exports.preprocess(parseIfString, deepStrict(inner)).describe(description);
9623
9966
  }
9624
- var SECTION_KEYS = ["aiAct", "economics", "actuals", "decisionLog", "statusReports", "requiredSkills", "capabilityImpacts"];
9967
+ var SECTION_KEYS = ["aiAct", "economics", "actuals", "decisionLog", "statusReports", "requiredSkills", "capabilityImpacts", "milestones"];
9625
9968
  var SECTION_SCHEMAS = Object.fromEntries(
9626
9969
  SECTION_KEYS.map((k) => [k, contractSection(k)])
9627
9970
  );
@@ -9632,6 +9975,7 @@ var SECTION_DESCRIPTIONS = {
9632
9975
  decisionLog: "Decision log entries \u2014 see sectionShapes.decisionLog. Entry ids are minted by the Composer \u2014 leave them out. Dates dd/mm/yyyy or yyyy-mm-dd.",
9633
9976
  statusReports: "Status reports \u2014 see sectionShapes.statusReports. Report ids are minted by the Composer \u2014 leave them out. Dates dd/mm/yyyy or yyyy-mm-dd.",
9634
9977
  capabilityImpacts: "Capability links [{capabilityId, kind: improve|new|replace|retire, maturityTo?}]. maturityTo 1\u20135 = level reached (omit = the capability's target; never for retire). capabilityId: a capability of the map, from read_portfolio_context \u2192 lists.capabilities; without the context leave the list empty.",
9978
+ milestones: "Milestones (max 30, title \u2264300 chars): baselineDate = the plan, forecastDate = today's expectation (omit = baseline), doneDate = reached. Dates dd/mm/yyyy or yyyy-mm-dd; ids minted. An update replaces the list: send all.",
9635
9979
  requiredSkills: "Required skills [{skillId, fte, runFte?}] \u2014 fte is the build-phase demand, the optional runFte the run-team demand after the planned end (absent = build fte continues, 0 = no run demand). skillId must be the id of a skill that exists in the organisation. With the portfolio context the Composer validates it (read_portfolio_context \u2192 lists.skills gives id + name); without it, leave the list empty and link skills in the app."
9636
9980
  };
9637
9981
  var contextWire = () => external_exports.preprocess(parseIfString, external_exports.union([external_exports.string().regex(/^ctx_[0-9a-f]{16}$/, "a contextId looks like ctx_<16 hex>"), external_exports.object({}).passthrough()]));
@@ -9676,6 +10020,7 @@ var compactSpecSchema = external_exports.object({
9676
10020
  statusReports: wireSection(SECTION_SCHEMAS.statusReports, SECTION_DESCRIPTIONS.statusReports).optional(),
9677
10021
  requiredSkills: wireSection(SECTION_SCHEMAS.requiredSkills, SECTION_DESCRIPTIONS.requiredSkills).optional(),
9678
10022
  capabilityImpacts: wireSection(SECTION_SCHEMAS.capabilityImpacts, SECTION_DESCRIPTIONS.capabilityImpacts).optional(),
10023
+ milestones: wireSection(SECTION_SCHEMAS.milestones, SECTION_DESCRIPTIONS.milestones).optional(),
9679
10024
  aiRiskTier: external_exports.enum(AI_RISK_TIERS).optional(),
9680
10025
  hitlPosture: external_exports.enum(HITL_POSTURES).optional(),
9681
10026
  dpiaStatus: external_exports.enum(DPIA_STATUSES).optional(),
@@ -10047,8 +10392,11 @@ function checkAiActVocabularies(block, errors) {
10047
10392
  }
10048
10393
  function mintNestedIds(rows, stamp, withStamps = false) {
10049
10394
  if (!rows) return void 0;
10395
+ const seen = /* @__PURE__ */ new Set();
10050
10396
  return rows.map((r) => {
10051
- const next = { ...r, id: isUuid(r.id) ? r.id : randomUUID() };
10397
+ const id = isUuid(r.id) && !seen.has(r.id) ? r.id : randomUUID();
10398
+ seen.add(id);
10399
+ const next = { ...r, id };
10052
10400
  if (withStamps) {
10053
10401
  if (!next.createdAt) next.createdAt = stamp;
10054
10402
  if (!next.updatedAt) next.updatedAt = stamp;
@@ -10095,6 +10443,31 @@ function assembleInitiative(input, now = /* @__PURE__ */ new Date()) {
10095
10443
  if (link.kind === "retire" && link.maturityTo !== void 0) errors.push(`capabilityImpacts.${i}.maturityTo: a retire link has no target level \u2014 omit maturityTo.`);
10096
10444
  else if (link.maturityTo !== void 0 && !Number.isInteger(link.maturityTo)) errors.push(`capabilityImpacts.${i}.maturityTo: must be a whole number 1\u20135 (got ${link.maturityTo}).`);
10097
10445
  }
10446
+ const milestones = spec.milestones ?? [];
10447
+ const pad = (n) => String(n).padStart(2, "0");
10448
+ const today = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}`;
10449
+ for (const [i, m] of milestones.entries()) {
10450
+ if (!m.title.trim()) errors.push(`milestones.${i}.title: must not be empty (got only spaces).`);
10451
+ for (const field of ["baselineDate", "forecastDate", "doneDate"]) {
10452
+ const v = m[field];
10453
+ if (v !== void 0 && !isCalendarDate(v)) errors.push(`milestones.${i}.${field}: "${v}" is not a real calendar date \u2014 dd/mm/yyyy or yyyy-mm-dd`);
10454
+ }
10455
+ const due = m.doneDate ?? m.forecastDate ?? m.baselineDate;
10456
+ if (isCalendarDate(due) && (spec.timelineStart && due < spec.timelineStart || spec.timelineEnd && due > spec.timelineEnd)) {
10457
+ warnings.push(`milestones.${i}: "${m.title.trim()}" falls on ${due}, outside the timeline ${spec.timelineStart} \u2013 ${spec.timelineEnd}.`);
10458
+ }
10459
+ if (m.doneDate && isCalendarDate(m.doneDate) && m.doneDate > today) warnings.push(`milestones.${i}.doneDate: ${m.doneDate} lies in the future \u2014 a done date marks a milestone already reached.`);
10460
+ }
10461
+ const norm2 = (v) => (v ?? "").trim().toLowerCase();
10462
+ const others = context?.initiatives ?? [];
10463
+ const ext = norm2(spec.externalId);
10464
+ const updates = spec.id !== void 0 || !!ext && others.filter((x) => norm2(x.externalId) === ext).length === 1 || others.some((x) => norm2(x.name) === norm2(spec.name));
10465
+ if (updates && spec.milestones === void 0) {
10466
+ warnings.push("milestones: none sent, and the app will offer this file as an update \u2014 it replaces the initiative's milestones, so any the app holds are removed. Send the full list to keep them.");
10467
+ }
10468
+ if (updates) {
10469
+ warnings.push("risks: this file cannot carry risks, and the app will offer it as an update \u2014 any risks the app holds for this initiative are removed. Re-enter them in the app after the import, or add the initiative's details there instead.");
10470
+ }
10098
10471
  let businessUnit = spec.businessUnit;
10099
10472
  let aiCategory = spec.aiCategory;
10100
10473
  if (context) {
@@ -10145,6 +10518,7 @@ function assembleInitiative(input, now = /* @__PURE__ */ new Date()) {
10145
10518
  evaluation,
10146
10519
  decisionLog: mintNestedIds(spec.decisionLog, stamp),
10147
10520
  statusReports: mintNestedIds(spec.statusReports, stamp),
10521
+ milestones: mintNestedIds(spec.milestones, stamp)?.map((m) => ({ ...m, title: m.title.trim() })),
10148
10522
  aiAct: aiAct ? { ...aiAct, ...aiAct.incidents ? { incidents: mintNestedIds(aiAct.incidents, stamp, true) } : {} } : void 0,
10149
10523
  createdAt: stamp,
10150
10524
  updatedAt: stamp
@@ -10214,7 +10588,7 @@ function createServer() {
10214
10588
  async () => text({
10215
10589
  capabilities: [
10216
10590
  "strict typed schemas: unknown keys anywhere in the spec are rejected with their exact path (never silently dropped)",
10217
- "sections (aiAct/economics/actuals/decisionLog/statusReports/requiredSkills/capabilityImpacts) accept a JSON object/array or the same JSON as a string; row ids are minted by the Composer",
10591
+ "sections (aiAct/economics/actuals/decisionLog/statusReports/requiredSkills/capabilityImpacts/milestones) accept a JSON object/array or the same JSON as a string; row ids are minted by the Composer",
10218
10592
  "dates accepted as dd/mm/yyyy, dd.mm.yyyy or yyyy-mm-dd (stored as yyyy-mm-dd)",
10219
10593
  "get_initiative_schema: sectionShapes, aiActVocabularies, portfolio-mode wording overlays",
10220
10594
  "AI-Act vocabulary and id-format enforcement with the allowed values in the error",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bicon/mcp-composer",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "description": "MCP server that helps an AI client compose a valid BICon portfolio initiative and hand it back as an import file (draft-first, no auth, no API calls).",
5
5
  "license": "UNLICENSED",
6
6
  "author": "BICon Establishment",