@bicon/mcp-composer 0.6.0 → 0.8.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 +9 -5
  2. package/dist/index.mjs +338 -105
  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, 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. |
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, risks, follow-ups, incidents — a client never invents ids; an id given to a milestone or risk is a label a follow-up's `milestoneId` / `riskId` can point at, and the link follows the minted id), **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,10 +93,14 @@ 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, milestones and incidents are minted by the
97
- Composer — a client-supplied UUID is kept, anything else replaced — because
98
- the app keys those rows per initiative and a re-used id from another
99
- initiative is exactly what collided on import once.
96
+ decision-log entries, status reports, milestones, risks, follow-ups and
97
+ incidents are minted by the Composer — a client-supplied UUID is kept, anything
98
+ else replaced — because the app keys those rows per initiative and a re-used id
99
+ from another initiative is exactly what collided on import once. A follow-up
100
+ links a milestone or risk by the id the spec gave that row (any label, `"m1"`),
101
+ and the link is rewritten to the minted id; a label that names no row, or two
102
+ rows, is an error, since the app would clear such a link on save without a
103
+ word.
100
104
 
101
105
  Errors the SDK raises before a handler runs (`Input validation error: …`) carry
102
106
  no `composerVersion` — that is normal. A *successful* result without it means an
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.6.0" : readPackageVersion();
15
+ var COMPOSER_VERSION = true ? "0.8.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, manage_milestones, manage_risks.")
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, manage_follow_ups.")
4174
4174
  });
4175
4175
  var ListOrganizationMembersResponse = arrayType(ListOrganizationMembersResponseItem);
4176
4176
  var SyncOrganizationMembersResponse = objectType({
@@ -4180,18 +4180,23 @@ 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, manage_milestones, manage_risks."),
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, manage_follow_ups."),
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
+ var ListOrganizationDirectoryResponseItem = objectType({
4187
+ "userId": stringType().uuid(),
4188
+ "name": stringType()
4189
+ });
4190
+ var ListOrganizationDirectoryResponse = arrayType(ListOrganizationDirectoryResponseItem);
4186
4191
  var UpdateOrganizationMemberPermissionsParams = objectType({
4187
4192
  "userId": coerce.string().uuid()
4188
4193
  });
4189
4194
  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, manage_milestones, manage_risks.")
4195
+ "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, manage_follow_ups.")
4191
4196
  });
4192
4197
  var UpdateOrganizationMemberPermissionsResponse = objectType({
4193
4198
  "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, manage_milestones, manage_risks.")
4199
+ "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, manage_follow_ups.")
4195
4200
  });
4196
4201
  var ListPermissionProfilesResponseItem = objectType({
4197
4202
  "id": stringType().uuid(),
@@ -4298,6 +4303,12 @@ var listSnapshotsResponseInitiativesItemRisksItemReviewDateRegExp = new RegExp("
4298
4303
  var listSnapshotsResponseInitiativesItemRisksItemOccurredDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
4299
4304
  var listSnapshotsResponseInitiativesItemRisksItemNoteMax = 1e4;
4300
4305
  var listSnapshotsResponseInitiativesItemRisksMax = 50;
4306
+ var listSnapshotsResponseInitiativesItemFollowUpsItemTitleMax = 300;
4307
+ var listSnapshotsResponseInitiativesItemFollowUpsItemAssigneeNameMax = 300;
4308
+ var listSnapshotsResponseInitiativesItemFollowUpsItemDueDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
4309
+ var listSnapshotsResponseInitiativesItemFollowUpsItemDoneDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
4310
+ var listSnapshotsResponseInitiativesItemFollowUpsItemNoteMax = 1e4;
4311
+ var listSnapshotsResponseInitiativesItemFollowUpsMax = 50;
4301
4312
  var listSnapshotsResponseInitiativesItemDependsOnMax = 1e3;
4302
4313
  var listSnapshotsResponseInitiativesItemRequiredSkillsItemRunFteMin = 0;
4303
4314
  var listSnapshotsResponseInitiativesItemRequiredSkillsMax = 1e3;
@@ -4523,6 +4534,17 @@ var ListSnapshotsResponseItem = objectType({
4523
4534
  "occurredDate": stringType().regex(listSnapshotsResponseInitiativesItemRisksItemOccurredDateRegExp).optional(),
4524
4535
  "note": stringType().max(listSnapshotsResponseInitiativesItemRisksItemNoteMax).optional()
4525
4536
  }).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(),
4537
+ "followUps": arrayType(objectType({
4538
+ "id": stringType(),
4539
+ "title": stringType().min(1).max(listSnapshotsResponseInitiativesItemFollowUpsItemTitleMax),
4540
+ "assigneeUserId": stringType().uuid().optional(),
4541
+ "assigneeName": stringType().max(listSnapshotsResponseInitiativesItemFollowUpsItemAssigneeNameMax).optional(),
4542
+ "dueDate": stringType().regex(listSnapshotsResponseInitiativesItemFollowUpsItemDueDateRegExp),
4543
+ "doneDate": stringType().regex(listSnapshotsResponseInitiativesItemFollowUpsItemDoneDateRegExp).optional(),
4544
+ "milestoneId": stringType().optional(),
4545
+ "riskId": stringType().optional(),
4546
+ "note": stringType().max(listSnapshotsResponseInitiativesItemFollowUpsItemNoteMax).optional()
4547
+ }).describe("An agreed next step: who does what by when (docs/risks-issues-follow-ups-concept-2026-10-19.md). assigneeUserId is a member of the org (an id that is not is dropped on save, the name kept); milestoneId and riskId name the same initiative's milestones and risks (a link that does not is cleared on save). Dates are yyyy-mm-dd.")).max(listSnapshotsResponseInitiativesItemFollowUpsMax).optional(),
4526
4548
  "dependsOn": arrayType(stringType()).max(listSnapshotsResponseInitiativesItemDependsOnMax),
4527
4549
  "requiredSkills": arrayType(objectType({
4528
4550
  "skillId": stringType(),
@@ -4678,6 +4700,12 @@ var createSnapshotBodyInitiativesItemRisksItemReviewDateRegExp = new RegExp("^\\
4678
4700
  var createSnapshotBodyInitiativesItemRisksItemOccurredDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
4679
4701
  var createSnapshotBodyInitiativesItemRisksItemNoteMax = 1e4;
4680
4702
  var createSnapshotBodyInitiativesItemRisksMax = 50;
4703
+ var createSnapshotBodyInitiativesItemFollowUpsItemTitleMax = 300;
4704
+ var createSnapshotBodyInitiativesItemFollowUpsItemAssigneeNameMax = 300;
4705
+ var createSnapshotBodyInitiativesItemFollowUpsItemDueDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
4706
+ var createSnapshotBodyInitiativesItemFollowUpsItemDoneDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
4707
+ var createSnapshotBodyInitiativesItemFollowUpsItemNoteMax = 1e4;
4708
+ var createSnapshotBodyInitiativesItemFollowUpsMax = 50;
4681
4709
  var createSnapshotBodyInitiativesItemDependsOnMax = 1e3;
4682
4710
  var createSnapshotBodyInitiativesItemRequiredSkillsItemRunFteMin = 0;
4683
4711
  var createSnapshotBodyInitiativesItemRequiredSkillsMax = 1e3;
@@ -4903,6 +4931,17 @@ var CreateSnapshotBody = objectType({
4903
4931
  "occurredDate": stringType().regex(createSnapshotBodyInitiativesItemRisksItemOccurredDateRegExp).optional(),
4904
4932
  "note": stringType().max(createSnapshotBodyInitiativesItemRisksItemNoteMax).optional()
4905
4933
  }).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(),
4934
+ "followUps": arrayType(objectType({
4935
+ "id": stringType(),
4936
+ "title": stringType().min(1).max(createSnapshotBodyInitiativesItemFollowUpsItemTitleMax),
4937
+ "assigneeUserId": stringType().uuid().optional(),
4938
+ "assigneeName": stringType().max(createSnapshotBodyInitiativesItemFollowUpsItemAssigneeNameMax).optional(),
4939
+ "dueDate": stringType().regex(createSnapshotBodyInitiativesItemFollowUpsItemDueDateRegExp),
4940
+ "doneDate": stringType().regex(createSnapshotBodyInitiativesItemFollowUpsItemDoneDateRegExp).optional(),
4941
+ "milestoneId": stringType().optional(),
4942
+ "riskId": stringType().optional(),
4943
+ "note": stringType().max(createSnapshotBodyInitiativesItemFollowUpsItemNoteMax).optional()
4944
+ }).describe("An agreed next step: who does what by when (docs/risks-issues-follow-ups-concept-2026-10-19.md). assigneeUserId is a member of the org (an id that is not is dropped on save, the name kept); milestoneId and riskId name the same initiative's milestones and risks (a link that does not is cleared on save). Dates are yyyy-mm-dd.")).max(createSnapshotBodyInitiativesItemFollowUpsMax).optional(),
4906
4945
  "dependsOn": arrayType(stringType()).max(createSnapshotBodyInitiativesItemDependsOnMax),
4907
4946
  "requiredSkills": arrayType(objectType({
4908
4947
  "skillId": stringType(),
@@ -5064,6 +5103,12 @@ var renameSnapshotResponseInitiativesItemRisksItemReviewDateRegExp = new RegExp(
5064
5103
  var renameSnapshotResponseInitiativesItemRisksItemOccurredDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
5065
5104
  var renameSnapshotResponseInitiativesItemRisksItemNoteMax = 1e4;
5066
5105
  var renameSnapshotResponseInitiativesItemRisksMax = 50;
5106
+ var renameSnapshotResponseInitiativesItemFollowUpsItemTitleMax = 300;
5107
+ var renameSnapshotResponseInitiativesItemFollowUpsItemAssigneeNameMax = 300;
5108
+ var renameSnapshotResponseInitiativesItemFollowUpsItemDueDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
5109
+ var renameSnapshotResponseInitiativesItemFollowUpsItemDoneDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
5110
+ var renameSnapshotResponseInitiativesItemFollowUpsItemNoteMax = 1e4;
5111
+ var renameSnapshotResponseInitiativesItemFollowUpsMax = 50;
5067
5112
  var renameSnapshotResponseInitiativesItemDependsOnMax = 1e3;
5068
5113
  var renameSnapshotResponseInitiativesItemRequiredSkillsItemRunFteMin = 0;
5069
5114
  var renameSnapshotResponseInitiativesItemRequiredSkillsMax = 1e3;
@@ -5289,6 +5334,17 @@ var RenameSnapshotResponse = objectType({
5289
5334
  "occurredDate": stringType().regex(renameSnapshotResponseInitiativesItemRisksItemOccurredDateRegExp).optional(),
5290
5335
  "note": stringType().max(renameSnapshotResponseInitiativesItemRisksItemNoteMax).optional()
5291
5336
  }).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(),
5337
+ "followUps": arrayType(objectType({
5338
+ "id": stringType(),
5339
+ "title": stringType().min(1).max(renameSnapshotResponseInitiativesItemFollowUpsItemTitleMax),
5340
+ "assigneeUserId": stringType().uuid().optional(),
5341
+ "assigneeName": stringType().max(renameSnapshotResponseInitiativesItemFollowUpsItemAssigneeNameMax).optional(),
5342
+ "dueDate": stringType().regex(renameSnapshotResponseInitiativesItemFollowUpsItemDueDateRegExp),
5343
+ "doneDate": stringType().regex(renameSnapshotResponseInitiativesItemFollowUpsItemDoneDateRegExp).optional(),
5344
+ "milestoneId": stringType().optional(),
5345
+ "riskId": stringType().optional(),
5346
+ "note": stringType().max(renameSnapshotResponseInitiativesItemFollowUpsItemNoteMax).optional()
5347
+ }).describe("An agreed next step: who does what by when (docs/risks-issues-follow-ups-concept-2026-10-19.md). assigneeUserId is a member of the org (an id that is not is dropped on save, the name kept); milestoneId and riskId name the same initiative's milestones and risks (a link that does not is cleared on save). Dates are yyyy-mm-dd.")).max(renameSnapshotResponseInitiativesItemFollowUpsMax).optional(),
5292
5348
  "dependsOn": arrayType(stringType()).max(renameSnapshotResponseInitiativesItemDependsOnMax),
5293
5349
  "requiredSkills": arrayType(objectType({
5294
5350
  "skillId": stringType(),
@@ -5445,6 +5501,12 @@ var listInitiativesResponseRisksItemReviewDateRegExp = new RegExp("^\\d{4}-\\d{2
5445
5501
  var listInitiativesResponseRisksItemOccurredDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
5446
5502
  var listInitiativesResponseRisksItemNoteMax = 1e4;
5447
5503
  var listInitiativesResponseRisksMax = 50;
5504
+ var listInitiativesResponseFollowUpsItemTitleMax = 300;
5505
+ var listInitiativesResponseFollowUpsItemAssigneeNameMax = 300;
5506
+ var listInitiativesResponseFollowUpsItemDueDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
5507
+ var listInitiativesResponseFollowUpsItemDoneDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
5508
+ var listInitiativesResponseFollowUpsItemNoteMax = 1e4;
5509
+ var listInitiativesResponseFollowUpsMax = 50;
5448
5510
  var listInitiativesResponseDependsOnMax = 1e3;
5449
5511
  var listInitiativesResponseRequiredSkillsItemRunFteMin = 0;
5450
5512
  var listInitiativesResponseRequiredSkillsMax = 1e3;
@@ -5664,6 +5726,17 @@ var ListInitiativesResponseItem = objectType({
5664
5726
  "occurredDate": stringType().regex(listInitiativesResponseRisksItemOccurredDateRegExp).optional(),
5665
5727
  "note": stringType().max(listInitiativesResponseRisksItemNoteMax).optional()
5666
5728
  }).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(),
5729
+ "followUps": arrayType(objectType({
5730
+ "id": stringType(),
5731
+ "title": stringType().min(1).max(listInitiativesResponseFollowUpsItemTitleMax),
5732
+ "assigneeUserId": stringType().uuid().optional(),
5733
+ "assigneeName": stringType().max(listInitiativesResponseFollowUpsItemAssigneeNameMax).optional(),
5734
+ "dueDate": stringType().regex(listInitiativesResponseFollowUpsItemDueDateRegExp),
5735
+ "doneDate": stringType().regex(listInitiativesResponseFollowUpsItemDoneDateRegExp).optional(),
5736
+ "milestoneId": stringType().optional(),
5737
+ "riskId": stringType().optional(),
5738
+ "note": stringType().max(listInitiativesResponseFollowUpsItemNoteMax).optional()
5739
+ }).describe("An agreed next step: who does what by when (docs/risks-issues-follow-ups-concept-2026-10-19.md). assigneeUserId is a member of the org (an id that is not is dropped on save, the name kept); milestoneId and riskId name the same initiative's milestones and risks (a link that does not is cleared on save). Dates are yyyy-mm-dd.")).max(listInitiativesResponseFollowUpsMax).optional(),
5667
5740
  "dependsOn": arrayType(stringType()).max(listInitiativesResponseDependsOnMax),
5668
5741
  "requiredSkills": arrayType(objectType({
5669
5742
  "skillId": stringType(),
@@ -5816,6 +5889,12 @@ var createInitiativeBodyOneRisksItemReviewDateRegExp = new RegExp("^\\d{4}-\\d{2
5816
5889
  var createInitiativeBodyOneRisksItemOccurredDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
5817
5890
  var createInitiativeBodyOneRisksItemNoteMax = 1e4;
5818
5891
  var createInitiativeBodyOneRisksMax = 50;
5892
+ var createInitiativeBodyOneFollowUpsItemTitleMax = 300;
5893
+ var createInitiativeBodyOneFollowUpsItemAssigneeNameMax = 300;
5894
+ var createInitiativeBodyOneFollowUpsItemDueDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
5895
+ var createInitiativeBodyOneFollowUpsItemDoneDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
5896
+ var createInitiativeBodyOneFollowUpsItemNoteMax = 1e4;
5897
+ var createInitiativeBodyOneFollowUpsMax = 50;
5819
5898
  var createInitiativeBodyOneDependsOnMax = 1e3;
5820
5899
  var createInitiativeBodyOneRequiredSkillsItemRunFteMin = 0;
5821
5900
  var createInitiativeBodyOneRequiredSkillsMax = 1e3;
@@ -6035,6 +6114,17 @@ var CreateInitiativeBody = objectType({
6035
6114
  "occurredDate": stringType().regex(createInitiativeBodyOneRisksItemOccurredDateRegExp).optional(),
6036
6115
  "note": stringType().max(createInitiativeBodyOneRisksItemNoteMax).optional()
6037
6116
  }).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(),
6117
+ "followUps": arrayType(objectType({
6118
+ "id": stringType(),
6119
+ "title": stringType().min(1).max(createInitiativeBodyOneFollowUpsItemTitleMax),
6120
+ "assigneeUserId": stringType().uuid().optional(),
6121
+ "assigneeName": stringType().max(createInitiativeBodyOneFollowUpsItemAssigneeNameMax).optional(),
6122
+ "dueDate": stringType().regex(createInitiativeBodyOneFollowUpsItemDueDateRegExp),
6123
+ "doneDate": stringType().regex(createInitiativeBodyOneFollowUpsItemDoneDateRegExp).optional(),
6124
+ "milestoneId": stringType().optional(),
6125
+ "riskId": stringType().optional(),
6126
+ "note": stringType().max(createInitiativeBodyOneFollowUpsItemNoteMax).optional()
6127
+ }).describe("An agreed next step: who does what by when (docs/risks-issues-follow-ups-concept-2026-10-19.md). assigneeUserId is a member of the org (an id that is not is dropped on save, the name kept); milestoneId and riskId name the same initiative's milestones and risks (a link that does not is cleared on save). Dates are yyyy-mm-dd.")).max(createInitiativeBodyOneFollowUpsMax).optional(),
6038
6128
  "dependsOn": arrayType(stringType()).max(createInitiativeBodyOneDependsOnMax),
6039
6129
  "requiredSkills": arrayType(objectType({
6040
6130
  "skillId": stringType(),
@@ -6197,6 +6287,12 @@ var getInitiativeResponseRisksItemReviewDateRegExp = new RegExp("^\\d{4}-\\d{2}-
6197
6287
  var getInitiativeResponseRisksItemOccurredDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
6198
6288
  var getInitiativeResponseRisksItemNoteMax = 1e4;
6199
6289
  var getInitiativeResponseRisksMax = 50;
6290
+ var getInitiativeResponseFollowUpsItemTitleMax = 300;
6291
+ var getInitiativeResponseFollowUpsItemAssigneeNameMax = 300;
6292
+ var getInitiativeResponseFollowUpsItemDueDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
6293
+ var getInitiativeResponseFollowUpsItemDoneDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
6294
+ var getInitiativeResponseFollowUpsItemNoteMax = 1e4;
6295
+ var getInitiativeResponseFollowUpsMax = 50;
6200
6296
  var getInitiativeResponseDependsOnMax = 1e3;
6201
6297
  var getInitiativeResponseRequiredSkillsItemRunFteMin = 0;
6202
6298
  var getInitiativeResponseRequiredSkillsMax = 1e3;
@@ -6416,6 +6512,17 @@ var GetInitiativeResponse = objectType({
6416
6512
  "occurredDate": stringType().regex(getInitiativeResponseRisksItemOccurredDateRegExp).optional(),
6417
6513
  "note": stringType().max(getInitiativeResponseRisksItemNoteMax).optional()
6418
6514
  }).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(),
6515
+ "followUps": arrayType(objectType({
6516
+ "id": stringType(),
6517
+ "title": stringType().min(1).max(getInitiativeResponseFollowUpsItemTitleMax),
6518
+ "assigneeUserId": stringType().uuid().optional(),
6519
+ "assigneeName": stringType().max(getInitiativeResponseFollowUpsItemAssigneeNameMax).optional(),
6520
+ "dueDate": stringType().regex(getInitiativeResponseFollowUpsItemDueDateRegExp),
6521
+ "doneDate": stringType().regex(getInitiativeResponseFollowUpsItemDoneDateRegExp).optional(),
6522
+ "milestoneId": stringType().optional(),
6523
+ "riskId": stringType().optional(),
6524
+ "note": stringType().max(getInitiativeResponseFollowUpsItemNoteMax).optional()
6525
+ }).describe("An agreed next step: who does what by when (docs/risks-issues-follow-ups-concept-2026-10-19.md). assigneeUserId is a member of the org (an id that is not is dropped on save, the name kept); milestoneId and riskId name the same initiative's milestones and risks (a link that does not is cleared on save). Dates are yyyy-mm-dd.")).max(getInitiativeResponseFollowUpsMax).optional(),
6419
6526
  "dependsOn": arrayType(stringType()).max(getInitiativeResponseDependsOnMax),
6420
6527
  "requiredSkills": arrayType(objectType({
6421
6528
  "skillId": stringType(),
@@ -6570,6 +6677,12 @@ var updateInitiativeBodyOneRisksItemReviewDateRegExp = new RegExp("^\\d{4}-\\d{2
6570
6677
  var updateInitiativeBodyOneRisksItemOccurredDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
6571
6678
  var updateInitiativeBodyOneRisksItemNoteMax = 1e4;
6572
6679
  var updateInitiativeBodyOneRisksMax = 50;
6680
+ var updateInitiativeBodyOneFollowUpsItemTitleMax = 300;
6681
+ var updateInitiativeBodyOneFollowUpsItemAssigneeNameMax = 300;
6682
+ var updateInitiativeBodyOneFollowUpsItemDueDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
6683
+ var updateInitiativeBodyOneFollowUpsItemDoneDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
6684
+ var updateInitiativeBodyOneFollowUpsItemNoteMax = 1e4;
6685
+ var updateInitiativeBodyOneFollowUpsMax = 50;
6573
6686
  var updateInitiativeBodyOneDependsOnMax = 1e3;
6574
6687
  var updateInitiativeBodyOneRequiredSkillsItemRunFteMin = 0;
6575
6688
  var updateInitiativeBodyOneRequiredSkillsMax = 1e3;
@@ -6789,6 +6902,17 @@ var UpdateInitiativeBody = objectType({
6789
6902
  "occurredDate": stringType().regex(updateInitiativeBodyOneRisksItemOccurredDateRegExp).optional(),
6790
6903
  "note": stringType().max(updateInitiativeBodyOneRisksItemNoteMax).optional()
6791
6904
  }).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(),
6905
+ "followUps": arrayType(objectType({
6906
+ "id": stringType(),
6907
+ "title": stringType().min(1).max(updateInitiativeBodyOneFollowUpsItemTitleMax),
6908
+ "assigneeUserId": stringType().uuid().optional(),
6909
+ "assigneeName": stringType().max(updateInitiativeBodyOneFollowUpsItemAssigneeNameMax).optional(),
6910
+ "dueDate": stringType().regex(updateInitiativeBodyOneFollowUpsItemDueDateRegExp),
6911
+ "doneDate": stringType().regex(updateInitiativeBodyOneFollowUpsItemDoneDateRegExp).optional(),
6912
+ "milestoneId": stringType().optional(),
6913
+ "riskId": stringType().optional(),
6914
+ "note": stringType().max(updateInitiativeBodyOneFollowUpsItemNoteMax).optional()
6915
+ }).describe("An agreed next step: who does what by when (docs/risks-issues-follow-ups-concept-2026-10-19.md). assigneeUserId is a member of the org (an id that is not is dropped on save, the name kept); milestoneId and riskId name the same initiative's milestones and risks (a link that does not is cleared on save). Dates are yyyy-mm-dd.")).max(updateInitiativeBodyOneFollowUpsMax).optional(),
6792
6916
  "dependsOn": arrayType(stringType()).max(updateInitiativeBodyOneDependsOnMax),
6793
6917
  "requiredSkills": arrayType(objectType({
6794
6918
  "skillId": stringType(),
@@ -6948,6 +7072,12 @@ var updateInitiativeResponseRisksItemReviewDateRegExp = new RegExp("^\\d{4}-\\d{
6948
7072
  var updateInitiativeResponseRisksItemOccurredDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
6949
7073
  var updateInitiativeResponseRisksItemNoteMax = 1e4;
6950
7074
  var updateInitiativeResponseRisksMax = 50;
7075
+ var updateInitiativeResponseFollowUpsItemTitleMax = 300;
7076
+ var updateInitiativeResponseFollowUpsItemAssigneeNameMax = 300;
7077
+ var updateInitiativeResponseFollowUpsItemDueDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
7078
+ var updateInitiativeResponseFollowUpsItemDoneDateRegExp = new RegExp("^\\d{4}-\\d{2}-\\d{2}$");
7079
+ var updateInitiativeResponseFollowUpsItemNoteMax = 1e4;
7080
+ var updateInitiativeResponseFollowUpsMax = 50;
6951
7081
  var updateInitiativeResponseDependsOnMax = 1e3;
6952
7082
  var updateInitiativeResponseRequiredSkillsItemRunFteMin = 0;
6953
7083
  var updateInitiativeResponseRequiredSkillsMax = 1e3;
@@ -7167,6 +7297,17 @@ var UpdateInitiativeResponse = objectType({
7167
7297
  "occurredDate": stringType().regex(updateInitiativeResponseRisksItemOccurredDateRegExp).optional(),
7168
7298
  "note": stringType().max(updateInitiativeResponseRisksItemNoteMax).optional()
7169
7299
  }).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(),
7300
+ "followUps": arrayType(objectType({
7301
+ "id": stringType(),
7302
+ "title": stringType().min(1).max(updateInitiativeResponseFollowUpsItemTitleMax),
7303
+ "assigneeUserId": stringType().uuid().optional(),
7304
+ "assigneeName": stringType().max(updateInitiativeResponseFollowUpsItemAssigneeNameMax).optional(),
7305
+ "dueDate": stringType().regex(updateInitiativeResponseFollowUpsItemDueDateRegExp),
7306
+ "doneDate": stringType().regex(updateInitiativeResponseFollowUpsItemDoneDateRegExp).optional(),
7307
+ "milestoneId": stringType().optional(),
7308
+ "riskId": stringType().optional(),
7309
+ "note": stringType().max(updateInitiativeResponseFollowUpsItemNoteMax).optional()
7310
+ }).describe("An agreed next step: who does what by when (docs/risks-issues-follow-ups-concept-2026-10-19.md). assigneeUserId is a member of the org (an id that is not is dropped on save, the name kept); milestoneId and riskId name the same initiative's milestones and risks (a link that does not is cleared on save). Dates are yyyy-mm-dd.")).max(updateInitiativeResponseFollowUpsMax).optional(),
7170
7311
  "dependsOn": arrayType(stringType()).max(updateInitiativeResponseDependsOnMax),
7171
7312
  "requiredSkills": arrayType(objectType({
7172
7313
  "skillId": stringType(),
@@ -7543,16 +7684,18 @@ var EN_DIGITAL = {
7543
7684
  "subHelp.dataAvailability": "Availability of the source systems, APIs and master data the solution depends on.",
7544
7685
  "subHelp.dataQuality": "Cleanliness, completeness and timeliness of the data flowing through the digital workflow.",
7545
7686
  "dim.feasibility.band1.meaning": "Data, solution or integration gaps make delivery uncertain.",
7546
- "dim.governance.band2.meaning": "Standard risk controls and monitoring required.",
7547
- "govBand.Low.desc": "0\u201320 \xB7 Low sensitivity \u2014 routine controls; no escalation required",
7548
- "govBand.Moderate.desc": "21\u201340 \xB7 Low sensitivity \u2014 routine controls suffice",
7549
- "govBand.Elevated.desc": "41\u201360 \xB7 Supervised operation \u2014 standard risk controls and monitoring required",
7550
- "govBand.High.desc": "61\u201380 \xB7 Restricted deployment \u2014 active board-level oversight, audit trail and access controls",
7687
+ "dim.governance.band2.meaning": "Standard monitoring; periodic review of the system's operation.",
7688
+ "dim.governance.band3.meaning": "Documented procedures, dual approvals and active monitoring required.",
7689
+ "govBand.Low.desc": "0\u201320 \xB7 Minimal oversight \u2014 routine controls; no escalation required",
7690
+ "govBand.Moderate.desc": "21\u201340 \xB7 Controlled operation \u2014 standard monitoring; periodic review",
7691
+ "govBand.Elevated.desc": "41\u201360 \xB7 Supervised operation required \u2014 documented procedures, dual approvals, active monitoring",
7692
+ "govBand.High.desc": "61\u201380 \xB7 Restricted rollout \u2014 active board-level oversight, audit trail and access controls",
7551
7693
  "govBand.Critical.desc": "81\u2013100 \xB7 High governance sensitivity \u2014 treat as material risk; ringfencing and continuous oversight",
7552
7694
  "govLabel.Controlled Automation": "Controlled Operation",
7553
7695
  "govLabel.Human-in-the-Loop Required": "Supervised Operation Required",
7554
7696
  "govLabel.Restricted Deployment": "Restricted Rollout",
7555
7697
  "memo.governance.intro": "{count} initiatives sit in the Restricted Rollout band or above (governance \u2265 61/100) and require active board-level monitoring.",
7698
+ "settings.guardrails.maxHighGovernanceSharePct.hint": "At most this share of active initiatives may carry a governance score above 60 (Restricted Rollout or higher).",
7556
7699
  "subHelp.modelRobustness": "Stability of the solution under load, edge cases and unexpected inputs.",
7557
7700
  "subHelp.reproducibility": "Maturity of the underlying cloud / platform stack \u2014 proven and supported (managed services, mature regions, SLAs) vs experimental or self-hosted.",
7558
7701
  "subHelp.explainability": "How clearly the system's behaviour and outputs can be explained to operators and end-users.",
@@ -7579,7 +7722,7 @@ var EN_DIGITAL = {
7579
7722
  "settings.prio.longTermBets": "Multi-Year Programmes",
7580
7723
  "settings.prio.incremental": "Continuous Improvement",
7581
7724
  "settings.prio.operatingModel": "Operating Model Modernisation",
7582
- "settings.prio.subtitle": "Thresholds used by the Prioritisation page to assign each digital initiative to a strategic archetype. Rules are evaluated top-to-bottom and the first match wins. All values are scores out of 100 across the four dimensions: V = Value & Scale, F = Delivery Feasibility & Operability, C = Compliance & Operational Risk, S = Strategic Impact.",
7725
+ "settings.prio.subtitle": "Thresholds used by the Prioritisation page to assign each digital initiative to a strategic archetype. Rules are listed in funding order, as on the Prioritisation page; each initiative is assigned by the first rule it matches, checked in the order of its precedence number. All values are scores out of 100 across the four dimensions: V = Value & Scale, F = Delivery Feasibility & Operability, C = Compliance & Operational Risk, S = Strategic Impact.",
7583
7726
  "inventory.col.scores": "Scores (V/F/C/S)",
7584
7727
  "concept.eyebrow": "Steering of AI, digital and transformation portfolios",
7585
7728
  "concept.title": "Turn fragmented digital projects into a managed portfolio.",
@@ -7642,10 +7785,10 @@ var EN_DIGITAL = {
7642
7785
  "method.s2.title": "2. Compliance & Operational Risk Classification",
7643
7786
  "method.s2.subtitle": "Compliance & operational-risk bands and what they imply for the control load.",
7644
7787
  "method.s2.intro": "Initiatives are classified into bands based on the Compliance & Operational Risk score:",
7645
- "method.s2.b2": "<strong>21\u201340 \xB7 Standard controls</strong>: standard monitoring; periodic review.",
7646
- "method.s2.b3": "<strong>41\u201360 \xB7 Enhanced operational controls</strong>: documented procedures, dual approvals, active monitoring.",
7788
+ "method.s2.b2": "<strong>21\u201340 \xB7 Controlled operation</strong>: standard monitoring; periodic review.",
7789
+ "method.s2.b3": "<strong>41\u201360 \xB7 Supervised operation required</strong>: documented procedures, dual approvals, active monitoring.",
7647
7790
  "method.s2.b4": "<strong>61\u201380 \xB7 Restricted rollout</strong>: active board-level oversight, audit trail and access controls.",
7648
- "method.s2.b5": "<strong>81\u2013100 \xB7 Board-level sponsorship required</strong>: treat as material risk; deploy only with explicit ringfencing.",
7791
+ "method.s2.b5": "<strong>81\u2013100 \xB7 High governance sensitivity</strong>: treat as material risk; deploy only with explicit ringfencing.",
7649
7792
  "method.s4.subtitle": "How each initiative is positioned on the Business Impact \xD7 Delivery Feasibility plane.",
7650
7793
  "method.s4.intro": "The x-axis (<strong>Business Impact</strong>) is the equal-weighted average of Value & Scale and Strategic Impact: <code>BusinessImpact = (Value + Strategic) / 2</code>. The y-axis is Delivery Feasibility & Operability. Quadrants are split deterministically at 50 on both axes:",
7651
7794
  "method.s4.scale": "<strong>Roll out</strong> \u2014 Business Impact \u2265 50 and Delivery Feasibility \u2265 50. High impact, reliably deliverable \u2014 ready for enterprise roll-out.",
@@ -7655,7 +7798,7 @@ var EN_DIGITAL = {
7655
7798
  "method.s4.bubbles": "Bubble size additionally emphasises Strategic Impact on its own (so a strategic initiative reads as a larger bubble even when its value score is moderate); bubble colour reflects the compliance & operational-risk band.",
7656
7799
  "method.s5.governance": "<strong>High Compliance & Operational Risk</strong> (precedence 3) \u2014 compliance & operational-risk score \u2265 {g} (and the initiative was not already classified as Quick Wins or Strategic Core). Elevated regulatory, compliance or operational-risk exposure that must be addressed before scaling.",
7657
7800
  "memo.assumptions.signals": "No external regulatory, operational-risk or third-party assurance signals have been incorporated into these scores.",
7658
- "method.s6.p1": 'The <a href="https://www.investopedia.com/terms/h/hhi.asp" target="_blank" rel="noopener noreferrer" class="text-primary underline underline-offset-2 hover:no-underline">Herfindahl\u2013Hirschman Index</a> is applied to four cuts of the portfolio: <strong>vendor strategy</strong>, <strong>solution type</strong>, <strong>digital category</strong>, and <strong>business unit</strong>.',
7801
+ "method.s6.p1": 'The <a href="https://www.investopedia.com/terms/h/hhi.asp" target="_blank" rel="noopener noreferrer" class="text-primary underline underline-offset-2 hover:no-underline">Herfindahl\u2013Hirschman Index</a> is applied to four cuts on the Concentration page: <strong>vendor strategy</strong>, <strong>digital category</strong>, <strong>business unit</strong> and <strong>compliance band</strong>. The board pack uses vendor, category, business unit and solution type, plus a weighted HHI.',
7659
7802
  "method.s6.p2": "A business-unit \xD7 digital-category cluster heatmap on the Concentration page surfaces specific over-exposed combinations beyond the aggregate.",
7660
7803
  "concept.problem.p1": "Many organisations are pursuing digital initiatives across a wide range of business processes. These initiatives often emerge from local experimentation within business units or technology teams rather than from a structured strategic process.",
7661
7804
  "concept.dim.value.body": "Economic leverage of the digital solution. Use cases addressing high-frequency, resource-intensive activities typically offer the greatest potential for economic impact; limited-scale or marginal-efficiency cases rarely justify the organisational effort required.",
@@ -7676,9 +7819,8 @@ var EN_DIGITAL = {
7676
7819
  "dim.valueScale.band1.meaning": "Confined to a single team or process with limited financial signal.",
7677
7820
  "dim.feasibility.band2.meaning": "Feasible but requires investment in data, integration or operability.",
7678
7821
  "dim.feasibility.band3.meaning": "Data, tooling and operability are in place to execute with confidence.",
7679
- "dim.governance.band2.label": "Supervised operation",
7680
- "dim.governance.band3.meaning": "Active board-level oversight, audit trail and access controls required for the digital system.",
7681
- "dim.strategic.band3.meaning": "Reshapes operating model, customer experience, or how data is used across the business.",
7822
+ "dim.governance.band4.meaning": "Active board-level oversight, audit trail and access controls required for the digital system.",
7823
+ "dim.strategic.band4.meaning": "Reshapes operating model, customer experience, or how data is used across the business.",
7682
7824
  "op.governance.detailLow": "Embedded delivery teams with part-time operational-risk coverage are typically sufficient at this load.",
7683
7825
  "boardPack.col.g": "C",
7684
7826
  // ── Concept & Methodology page theming ────────────────────────────────
@@ -7698,14 +7840,9 @@ var EN_DIGITAL = {
7698
7840
  "concept.features.f24.body": "Self-contained demo portfolios per mode (AI / Digital / Innovation) load with realistic initiatives and dependencies \u2014 so new users can explore every view immediately without entering data.",
7699
7841
  "concept.features.f29.body": "Run the console as a multi-tenant SaaS: each organisation is an isolated tenant with its own portfolio and data. Members sign in through managed authentication and get role-based access \u2014 admin, member or viewer \u2014 refined by granular per-section permissions an admin grants from Settings, enforced on both the server and the UI. Every governance-critical and Core Metadata change is captured in a per-field audit trail with the acting user and a timestamp, and each initiative shows who created and last edited it. Cloud sync keeps the shared portfolio consistent across the team, while local (no-account) mode still works for a single user. Privileged admin actions \u2014 access grants, role and permission changes, settings, profile and initiative changes \u2014 are additionally recorded in an organisation-level admin activity log in Settings.",
7700
7842
  "concept.features.f30.body": "A rules-based, severity-ranked list of the decisions the portfolio's own data calls for: stop/defer candidates, gate discipline, capacity and budget shortfalls, and concentration. Benefits-realisation rules flag production systems that under-deliver \u2014 or never measure \u2014 their promised value. Board-set guardrails add the red lines: admins define policy limits in Settings \u2014 a budget-concentration cap per business unit, a value floor for funded initiatives and a compliance-load ceiling \u2014 each showing a live pass/fail, and every breach lands here as a decide-now item.",
7701
- "method.rules.r1.formula": "Value \xD7 Delivery Feasibility \u2192 Portfolio shape",
7702
- "method.rules.r1.explanation": "Quadrant placement on the Value \xD7 Delivery-Feasibility map drives the go / scale / pilot / stop decision for each initiative.",
7703
- "method.rules.r2.formula": "Compliance Band \u2192 Veto criterion",
7704
- "method.rules.r2.explanation": "Any initiative above the restricted band (Compliance & Operational Risk \u2265 61) cannot scale until explicit board-level controls are in place; it is removed from the prioritised list regardless of value or feasibility.",
7705
- "method.rules.r4.explanation": "If any portfolio cut (vendor, solution type, digital category, or business unit) exceeds HHI 0.25 on the normalised 0\u20131 scale, the portfolio steward must actively consider redistribution before approving new initiatives in the dominant segment.",
7706
7843
  "method.s1.dimensions.feasibility": "<strong>Delivery Feasibility &amp; Operability</strong> \u2014 buildability, operability and transparency.",
7707
7844
  "method.s1.dimensions.governance": "<strong>Compliance &amp; Operational Risk</strong> \u2014 regulatory, compliance and operational-risk load (deep dive in \xA7 3).",
7708
- "method.s2.b1": "<strong>0\u201320 \xB7 Low sensitivity</strong>: routine controls suffice.",
7845
+ "method.s2.b1": "<strong>0\u201320 \xB7 Minimal oversight</strong>: routine controls suffice.",
7709
7846
  "method.s5.intro": "Each initiative is evaluated against the rules below and assigned to the <em>first</em> category whose rule matches, in the precedence order <strong>1 \u2192 2 \u2192 3 \u2192 4 \u2192 5 \u2192 6 \u2192 7</strong>. The list below is shown in the same order the Prioritisation page renders the groups, which is not the same as precedence \u2014 the precedence number is given on each rule. Initiatives that satisfy none of rules 1\u20136 fall into the fallback group <em>Tactical / Uncategorised</em> (precedence 7).",
7710
7847
  "method.s5.quickWins": "<strong>Quick Wins</strong> (precedence 1) \u2014 value \u2265 {v}, feasibility \u2265 {f}, and compliance & operational risk \u2264 {g}. High return, low risk, ready to execute.",
7711
7848
  "method.s5.strategicCore": "<strong>Strategic Platform Initiatives</strong> (precedence 2) \u2014 value \u2265 {v}, feasibility \u2265 {f}, and strategic \u2265 {s}. Core platform bets that are both valuable and strategically central.",
@@ -7713,7 +7850,7 @@ var EN_DIGITAL = {
7713
7850
  "method.s5.longTerm": "<strong>Multi-Year Programmes</strong> (precedence 4) \u2014 value \u2265 {v}, feasibility &lt; {f}, and strategic \u2265 {s} (after High Compliance Risk has already claimed initiatives above its threshold). Strategically attractive but not yet feasible \u2014 keep on the horizon.",
7714
7851
  "method.s5.incremental": "<strong>Continuous Improvement</strong> (precedence 5) \u2014 value &lt; {v}, feasibility \u2265 {f}, and strategic &lt; {s}. Easy to ship but limited upside; useful as fillers.",
7715
7852
  "method.s5.uncategorised": "<strong>Tactical / Uncategorised</strong> (precedence 7) \u2014 fallback for initiatives that don't satisfy any of rules 1\u20136. Treat as tactical until scores sharpen.",
7716
- "method.s5.ranking": "<strong>Ranking inside the queue.</strong> Initiatives are first grouped by the category rules above (precedence 1 \u2192 7), then within each category ordered by <strong>Value</strong> score descending, then \u2014 if Value-at-Stake weighting is enabled in Settings and the row sits in Quick Wins / Strategic Platform Initiatives \u2014 Year-3 benefit descending. Final tie-break is <strong>Strategic Impact</strong> descending, then name A\u2192Z, so the result is deterministic and reproducible.",
7853
+ "method.s5.ranking": "<strong>Ranking inside the queue.</strong> Initiatives are first grouped by category in the order listed above (the order the Prioritisation page shows them), then within each category ordered by <strong>Value</strong> score descending, then \u2014 if Value-at-Stake weighting is enabled in Settings and the row sits in Quick Wins / Strategic Platform Initiatives \u2014 Year-3 benefit descending. Final tie-break is <strong>Strategic Impact</strong> descending, then name A\u2192Z, so the result is deterministic and reproducible.",
7717
7854
  "method.s10.p7": "<strong>Quick Win definition.</strong> The Quick Wins category requires fast time-to-value. Therefore a Quick Win that depends on an active non-Quick-Win upstream (Strategic Platform Initiative, Operating Model Modernisation, High Compliance Risk etc.) is automatically demoted out of Quick Wins \u2014 the upstream's pre-work makes it no longer quick. The rule is transitive: if A depends on B, and B is itself demoted, A is also demoted in the next iteration.",
7718
7855
  "method.audit.scope.governance": "<strong>Status</strong> and the four <strong>evaluation dimension scores</strong> (Value, Delivery Feasibility, Compliance &amp; Operational Risk, Strategic Impact) with their confidence.",
7719
7856
  "method.audit.scope.metadata": "<strong>All Core Metadata fields</strong> \u2014 name, business unit, owner, description, timeline, budget, vendor strategy, solution type, digital category and tags.",
@@ -7760,16 +7897,18 @@ var DE_DIGITAL = {
7760
7897
  "subHelp.dataAvailability": "Verf\xFCgbarkeit der Quellsysteme, Schnittstellen und Stammdaten, von denen die L\xF6sung abh\xE4ngt.",
7761
7898
  "subHelp.dataQuality": "Sauberkeit, Vollst\xE4ndigkeit und Aktualit\xE4t der Daten im digitalen Workflow.",
7762
7899
  "dim.feasibility.band1.meaning": "L\xFCcken bei Daten, L\xF6sung oder Integration machen die Umsetzung unsicher.",
7763
- "dim.governance.band2.meaning": "Standard-Risikokontrollen und Monitoring erforderlich.",
7764
- "govBand.Low.desc": "0\u201320 \xB7 Geringe Sensitivit\xE4t \u2014 Routinekontrollen; keine Eskalation erforderlich",
7765
- "govBand.Moderate.desc": "21\u201340 \xB7 Geringe Sensitivit\xE4t \u2014 Routinekontrollen ausreichend",
7766
- "govBand.Elevated.desc": "41\u201360 \xB7 \xDCberwachter Betrieb \u2014 Standard-Risikokontrollen und Monitoring erforderlich",
7767
- "govBand.High.desc": "61\u201380 \xB7 Eingeschr\xE4nkter Einsatz \u2014 aktive Vorstandsaufsicht, Audit-Trail und Zugriffskontrollen",
7900
+ "dim.governance.band2.meaning": "Standardmonitoring; regelm\xE4ssige \xDCberpr\xFCfung des Betriebs.",
7901
+ "dim.governance.band3.meaning": "Dokumentierte Verfahren, Vier-Augen-Prinzip und aktives Monitoring erforderlich.",
7902
+ "govBand.Low.desc": "0\u201320 \xB7 Minimale Aufsicht \u2014 Routinekontrollen; keine Eskalation erforderlich",
7903
+ "govBand.Moderate.desc": "21\u201340 \xB7 Kontrollierter Betrieb \u2014 Standardmonitoring; regelm\xE4ssige \xDCberpr\xFCfung",
7904
+ "govBand.Elevated.desc": "41\u201360 \xB7 Beaufsichtigter Betrieb erforderlich \u2014 dokumentierte Verfahren, Vier-Augen-Prinzip, aktives Monitoring",
7905
+ "govBand.High.desc": "61\u201380 \xB7 Eingeschr\xE4nkter Rollout \u2014 aktive Vorstandsaufsicht, Audit-Trail und Zugriffskontrollen",
7768
7906
  "govBand.Critical.desc": "81\u2013100 \xB7 Hohe Governance-Sensitivit\xE4t \u2014 als wesentliches Risiko behandeln; Ringfencing und kontinuierliche Aufsicht",
7769
7907
  "govLabel.Controlled Automation": "Kontrollierter Betrieb",
7770
7908
  "govLabel.Human-in-the-Loop Required": "Beaufsichtigter Betrieb erforderlich",
7771
7909
  "govLabel.Restricted Deployment": "Eingeschr\xE4nkter Rollout",
7772
7910
  "memo.governance.intro": "{count} Initiativen liegen im Band \u201EEingeschr\xE4nkter Rollout\u201C oder dar\xFCber (Governance \u2265 61/100) und ben\xF6tigen aktive Vorstandsaufsicht.",
7911
+ "settings.guardrails.maxHighGovernanceSharePct.hint": "H\xF6chstens dieser Anteil der aktiven Initiativen darf einen Governance-Score \xFCber 60 tragen (Eingeschr\xE4nkter Rollout oder h\xF6her).",
7773
7912
  "subHelp.modelRobustness": "Stabilit\xE4t der L\xF6sung unter Last, bei Edge-Cases und unerwarteten Eingaben.",
7774
7913
  "subHelp.reproducibility": "Reife des zugrundeliegenden Cloud-/Plattform-Stacks \u2014 bew\xE4hrt und supportet (Managed Services, etablierte Regionen, SLAs) vs. experimentell oder selbstgehostet.",
7775
7914
  "subHelp.explainability": "Wie klar Verhalten und Ergebnisse des Systems Betreibern und Endnutzern erkl\xE4rbar sind.",
@@ -7796,7 +7935,7 @@ var DE_DIGITAL = {
7796
7935
  "settings.prio.longTermBets": "Mehrjahresprogramme",
7797
7936
  "settings.prio.incremental": "Kontinuierliche Verbesserung",
7798
7937
  "settings.prio.operatingModel": "Betriebsmodell-Modernisierung",
7799
- "settings.prio.subtitle": "Schwellenwerte, mit denen die Priorisierungsseite jede digitale Initiative einem strategischen Archetyp zuordnet. Die Regeln werden von oben nach unten gepr\xFCft, die erste \xDCbereinstimmung gewinnt. Alle Werte sind Punkte von 0\u2013100 \xFCber die vier Dimensionen: W = Wert & Skalierung, M = Umsetzbarkeit & Betreibbarkeit, C = Compliance & Betriebsrisiko, S = Strategischer Impact.",
7938
+ "settings.prio.subtitle": "Schwellenwerte, mit denen die Priorisierungsseite jede digitale Initiative einem strategischen Archetyp zuordnet. Die Regeln stehen in F\xF6rderreihenfolge wie auf der Priorisierungsseite; jede Initiative wird der ersten Regel zugeordnet, die sie erf\xFCllt, gepr\xFCft in der Reihenfolge der Pr\xE4zedenznummer. Alle Werte sind Punkte von 0\u2013100 \xFCber die vier Dimensionen: W = Wert & Skalierung, M = Umsetzbarkeit & Betreibbarkeit, C = Compliance & Betriebsrisiko, S = Strategischer Impact.",
7800
7939
  "inventory.col.scores": "Punkte (W/M/C/S)",
7801
7940
  "concept.eyebrow": "Steuerung von KI-, Digital- und Transformationsportfolios",
7802
7941
  "concept.title": "Fragmentierte Digitalprojekte in ein gesteuertes Portfolio verwandeln.",
@@ -7859,10 +7998,10 @@ var DE_DIGITAL = {
7859
7998
  "method.s2.title": "2. Compliance- & Betriebsrisiko-Klassifikation",
7860
7999
  "method.s2.subtitle": "Compliance- & Betriebsrisiko-B\xE4nder und was sie f\xFCr die Kontroll-Last bedeuten.",
7861
8000
  "method.s2.intro": "Initiativen werden auf Basis des Compliance- & Betriebsrisiko-Werts klassifiziert:",
7862
- "method.s2.b2": "<strong>21\u201340 \xB7 Standard-Kontrollen</strong>: Standardmonitoring; regelm\xE4ssige \xDCberpr\xFCfung.",
7863
- "method.s2.b3": "<strong>41\u201360 \xB7 Erweiterte Betriebskontrollen</strong>: dokumentierte Verfahren, Vier-Augen-Prinzip, aktives Monitoring.",
8001
+ "method.s2.b2": "<strong>21\u201340 \xB7 Kontrollierter Betrieb</strong>: Standardmonitoring; regelm\xE4ssige \xDCberpr\xFCfung.",
8002
+ "method.s2.b3": "<strong>41\u201360 \xB7 Beaufsichtigter Betrieb erforderlich</strong>: dokumentierte Verfahren, Vier-Augen-Prinzip, aktives Monitoring.",
7864
8003
  "method.s2.b4": "<strong>61\u201380 \xB7 Eingeschr\xE4nkter Rollout</strong>: aktive Vorstandsaufsicht, Audit-Trail und Zugriffskontrollen.",
7865
- "method.s2.b5": "<strong>81\u2013100 \xB7 Vorstandspatenschaft erforderlich</strong>: als wesentliches Risiko behandeln; nur mit Ringfencing einsetzen.",
8004
+ "method.s2.b5": "<strong>81\u2013100 \xB7 Hohe Governance-Sensitivit\xE4t</strong>: als wesentliches Risiko behandeln; nur mit Ringfencing einsetzen.",
7866
8005
  "method.s4.subtitle": "Wie jede Initiative auf der Business-Impact-\xD7-Liefer-Machbarkeit-Ebene positioniert wird.",
7867
8006
  "method.s4.intro": "Die x-Achse (<strong>Business Impact</strong>) ist der gleichgewichtete Mittelwert aus Wert & Skalierung und strategischem Impact: <code>BusinessImpact = (Wert + Strategisch) / 2</code>. Die y-Achse ist Liefer-Machbarkeit & Betreibbarkeit. Die Quadranten werden deterministisch bei 50 auf beiden Achsen geteilt:",
7868
8007
  "method.s4.scale": "<strong>Ausrollen</strong> \u2014 Business Impact \u2265 50 und Liefer-Machbarkeit \u2265 50. Hoher Impact, verl\xE4sslich lieferbar \u2014 bereit f\xFCr unternehmensweiten Roll-out.",
@@ -7872,7 +8011,7 @@ var DE_DIGITAL = {
7872
8011
  "method.s4.bubbles": "Die Blasengr\xF6sse betont zus\xE4tzlich den strategischen Impact f\xFCr sich (eine strategische Initiative erscheint also gr\xF6sser, selbst wenn ihr Wert-Score moderat ist); die Farbe spiegelt das Compliance- & Betriebsrisiko-Band wider.",
7873
8012
  "method.s5.governance": "<strong>Hohes Compliance- & Betriebsrisiko</strong> (Pr\xE4zedenz 3) \u2014 Compliance- & Betriebsrisiko-Wert \u2265 {g} (und die Initiative wurde nicht bereits als Quick Wins oder Strategische Kerninitiative klassifiziert). Erh\xF6hte regulatorische, Compliance- oder Betriebsrisiko-Exposition, die vor einer Skalierung adressiert werden muss.",
7874
8013
  "memo.assumptions.signals": "Es wurden keine externen regulatorischen, Betriebsrisiko- oder Drittparteien-Signale in diese Scores einbezogen.",
7875
- "method.s6.p1": 'Der <a href="https://www.investopedia.com/terms/h/hhi.asp" target="_blank" rel="noopener noreferrer" class="text-primary underline underline-offset-2 hover:no-underline">Herfindahl\u2013Hirschman-Index</a> wird auf vier Schnitte angewendet: <strong>Anbieterstrategie</strong>, <strong>L\xF6sungstyp</strong>, <strong>Digital-Kategorie</strong> und <strong>Gesch\xE4ftseinheit</strong>.',
8014
+ "method.s6.p1": 'Der <a href="https://www.investopedia.com/terms/h/hhi.asp" target="_blank" rel="noopener noreferrer" class="text-primary underline underline-offset-2 hover:no-underline">Herfindahl\u2013Hirschman-Index</a> wird auf vier Schnitte der Konzentrationsseite angewendet: <strong>Anbieterstrategie</strong>, <strong>Digital-Kategorie</strong>, <strong>Gesch\xE4ftseinheit</strong> und <strong>Compliance-Band</strong>. Das Board-Pack verwendet Anbieter, Kategorie, Gesch\xE4ftseinheit und L\xF6sungstyp sowie einen gewichteten HHI.',
7876
8015
  "method.s6.p2": "Eine Gesch\xE4ftseinheit-\xD7-Digital-Kategorie-Heatmap auf der Konzentrations-Seite deckt dar\xFCber hinaus spezifische \xFCberexponierte Kombinationen jenseits des Aggregats auf.",
7877
8016
  "concept.problem.p1": "Viele Organisationen verfolgen Digital-Initiativen \xFCber eine Vielzahl von Gesch\xE4ftsprozessen hinweg. Diese Initiativen entstehen h\xE4ufig aus lokalen Experimenten in einzelnen Gesch\xE4ftseinheiten oder Technologieteams \u2013 nicht aus einem strukturierten strategischen Prozess.",
7878
8017
  "concept.dim.value.body": "\xD6konomischer Hebel der digitalen L\xF6sung. Anwendungsf\xE4lle mit hochfrequenten, ressourcenintensiven Aktivit\xE4ten bieten das gr\xF6sste Potenzial f\xFCr \xF6konomische Wirkung; F\xE4lle mit begrenztem Volumen oder marginalen Effizienzgewinnen rechtfertigen den organisatorischen Aufwand selten.",
@@ -7893,9 +8032,8 @@ var DE_DIGITAL = {
7893
8032
  "dim.valueScale.band1.meaning": "Auf ein einzelnes Team oder einen Prozess begrenzt; geringer finanzieller Effekt.",
7894
8033
  "dim.feasibility.band2.meaning": "Machbar, erfordert aber Investitionen in Daten, Integration oder Betreibbarkeit.",
7895
8034
  "dim.feasibility.band3.meaning": "Daten, Tools und Betreibbarkeit sind vorhanden, um mit Vertrauen umzusetzen.",
7896
- "dim.governance.band2.label": "\xDCberwachter Betrieb",
7897
- "dim.governance.band3.meaning": "Aktive Vorstandsaufsicht, Audit-Trail und Zugriffskontrollen f\xFCr das digitale System erforderlich.",
7898
- "dim.strategic.band3.meaning": "Ver\xE4ndert Betriebsmodell, Kundenerlebnis oder die Datennutzung im Unternehmen.",
8035
+ "dim.governance.band4.meaning": "Aktive Vorstandsaufsicht, Audit-Trail und Zugriffskontrollen f\xFCr das digitale System erforderlich.",
8036
+ "dim.strategic.band4.meaning": "Ver\xE4ndert Betriebsmodell, Kundenerlebnis oder die Datennutzung im Unternehmen.",
7899
8037
  "op.governance.detailLow": "Eingebettete Teams mit teilweiser Betriebsrisiko-Abdeckung reichen bei dieser Last meist aus.",
7900
8038
  "boardPack.col.g": "C",
7901
8039
  // ── Concept & Methodology page theming ────────────────────────────────
@@ -7915,14 +8053,9 @@ var DE_DIGITAL = {
7915
8053
  "concept.features.f24.body": "In sich geschlossene Demo-Portfolios pro Modus (KI / Digital / Innovation) laden mit realistischen Initiativen und Abh\xE4ngigkeiten \u2014 sodass neue Nutzer jede Sicht sofort erkunden k\xF6nnen, ohne Daten einzugeben.",
7916
8054
  "concept.features.f29.body": "Die Konsole l\xE4uft als mandantenf\xE4hige SaaS: Jede Organisation ist ein isolierter Mandant mit eigenem Portfolio und eigenen Daten. Mitglieder melden sich \xFCber eine verwaltete Authentifizierung an und erhalten rollenbasierten Zugriff \u2014 Admin, Mitglied oder Betrachter \u2014 verfeinert durch granulare Berechtigungen pro Bereich, die ein Admin in den Einstellungen vergibt und die serverseitig wie auch in der Oberfl\xE4che durchgesetzt werden. Jede governance-kritische und Kern-Metadaten-\xC4nderung wird in einem feldgenauen Audit-Trail mit handelndem Benutzer und Zeitstempel erfasst, und jede Initiative zeigt, wer sie erstellt und zuletzt bearbeitet hat. Cloud-Sync h\xE4lt das gemeinsame Portfolio im Team konsistent, w\xE4hrend der lokale Modus (ohne Konto) weiterhin f\xFCr einen einzelnen Nutzer funktioniert. Privilegierte Admin-Aktionen \u2014 Zugriffsvergaben, Rollen- und Rechte\xE4nderungen, \xC4nderungen an Einstellungen, Profilen und Initiativen \u2014 werden zus\xE4tzlich in einem Admin-Aktivit\xE4tsprotokoll auf Organisationsebene in den Einstellungen erfasst.",
7917
8055
  "concept.features.f30.body": "Eine regelbasierte, nach Dringlichkeit sortierte Liste der Entscheidungen, die die Portfoliodaten selbst einfordern: Stopp-/Aufschub-Kandidaten, Gate-Disziplin, Kapazit\xE4ts- und Budgetengp\xE4sse sowie Konzentration. Nutzenrealisierungs-Regeln markieren Produktionssysteme, die ihren zugesagten Nutzen verfehlen \u2014 oder nie messen. Vom Board gesetzte Leitplanken erg\xE4nzen die roten Linien: Admins definieren Richtwerte in den Einstellungen \u2014 Budgetkonzentrations-Obergrenze je Gesch\xE4ftsbereich, Wert-Untergrenze f\xFCr finanzierte Initiativen und Compliance-Last-Obergrenze \u2014 jeweils mit Live-Pr\xFCfung, und jeder Verstoss erscheint hier als Entscheidungspunkt.",
7918
- "method.rules.r1.formula": "Nutzen \xD7 Liefer-Machbarkeit \u2192 Portfolio-Gestalt",
7919
- "method.rules.r1.explanation": "Die Quadrantenposition auf der Nutzen-\xD7-Liefer-Machbarkeits-Karte bestimmt die Go-/Skalieren-/Pilot-/Stopp-Entscheidung f\xFCr jede Initiative.",
7920
- "method.rules.r2.formula": "Compliance-Band \u2192 Veto-Kriterium",
7921
- "method.rules.r2.explanation": "Jede Initiative oberhalb des Restricted-Bands (Compliance & Betriebsrisiko \u2265 61) darf nicht skaliert werden, solange keine expliziten Vorstandskontrollen vorhanden sind; sie wird unabh\xE4ngig von Nutzen oder Machbarkeit von der Priorisierungsliste entfernt.",
7922
- "method.rules.r4.explanation": "\xDCbersteigt ein Portfolio-Schnitt (Anbieter, L\xF6sungstyp, Digital-Kategorie oder Gesch\xE4ftseinheit) den HHI 0,25 auf der normierten 0\u20131-Skala, muss der Portfolio-Steward eine Umverteilung aktiv pr\xFCfen, bevor neue Initiativen im dominanten Segment freigegeben werden.",
7923
8056
  "method.s1.dimensions.feasibility": "<strong>Liefer-Machbarkeit &amp; Betreibbarkeit</strong> \u2014 Umsetzbarkeit, Betreibbarkeit und Transparenz.",
7924
8057
  "method.s1.dimensions.governance": "<strong>Compliance &amp; Betriebsrisiko</strong> \u2014 regulatorische, Compliance- und Betriebsrisiko-Last (Vertiefung in \xA7 3).",
7925
- "method.s2.b1": "<strong>0\u201320 \xB7 Geringe Sensitivit\xE4t</strong>: Routinekontrollen gen\xFCgen.",
8058
+ "method.s2.b1": "<strong>0\u201320 \xB7 Minimale Aufsicht</strong>: Routinekontrollen gen\xFCgen.",
7926
8059
  "method.s5.intro": "Jede Initiative wird gegen die folgenden Regeln gepr\xFCft und der <em>ersten</em> Kategorie zugeordnet, deren Regel zutrifft \u2014 in der Pr\xE4zedenzreihenfolge <strong>1 \u2192 2 \u2192 3 \u2192 4 \u2192 5 \u2192 6 \u2192 7</strong>. Die Liste unten erscheint in derselben Reihenfolge, in der die Priorisierungsseite die Gruppen darstellt; das entspricht nicht der Pr\xE4zedenz \u2014 die Pr\xE4zedenznummer steht jeweils an der Regel. Initiativen, die keine der Regeln 1\u20136 erf\xFCllen, landen in der Auffangkategorie <em>Taktisch / nicht kategorisiert</em> (Pr\xE4zedenz 7).",
7927
8060
  "method.s5.quickWins": "<strong>Quick Wins</strong> (Pr\xE4zedenz 1) \u2014 Wert \u2265 {v}, Machbarkeit \u2265 {f} und Compliance & Betriebsrisiko \u2264 {g}. Hoher Nutzen, geringes Risiko, umsetzungsreif.",
7928
8061
  "method.s5.strategicCore": "<strong>Strategische Plattform-Initiativen</strong> (Pr\xE4zedenz 2) \u2014 Wert \u2265 {v}, Machbarkeit \u2265 {f} und Strategie \u2265 {s}. Kern-Plattform-Wetten, die zugleich wertvoll und strategisch zentral sind.",
@@ -7930,7 +8063,7 @@ var DE_DIGITAL = {
7930
8063
  "method.s5.longTerm": "<strong>Mehrjahresprogramme</strong> (Pr\xE4zedenz 4) \u2014 Wert \u2265 {v}, Machbarkeit &lt; {f} und Strategie \u2265 {s} (nachdem Hohes Compliance-Risiko Initiativen oberhalb seines Schwellenwerts bereits beansprucht hat). Strategisch attraktiv, aber noch nicht machbar \u2014 am Horizont halten.",
7931
8064
  "method.s5.incremental": "<strong>Kontinuierliche Verbesserung</strong> (Pr\xE4zedenz 5) \u2014 Wert &lt; {v}, Machbarkeit \u2265 {f} und Strategie &lt; {s}. Leicht umsetzbar, aber begrenzter Nutzen; geeignet als F\xFCllinitiativen.",
7932
8065
  "method.s5.uncategorised": "<strong>Taktisch / nicht kategorisiert</strong> (Pr\xE4zedenz 7) \u2014 Auffangkategorie f\xFCr Initiativen, die keine der Regeln 1\u20136 erf\xFCllen. Bis zur Sch\xE4rfung der Bewertung taktisch behandeln.",
7933
- "method.s5.ranking": "<strong>Reihenfolge innerhalb der Warteschlange.</strong> Initiativen werden zuerst nach den Kategorie-Regeln oben gruppiert (Pr\xE4zedenz 1 \u2192 7), dann innerhalb jeder Kategorie nach <strong>Value</strong>-Score absteigend geordnet, dann \u2014 wenn die Value-at-Stake-Gewichtung in den Einstellungen aktiv ist und die Zeile in Quick Wins / Strategische Plattform-Initiativen liegt \u2014 nach Jahr-3-Nutzen absteigend. Letzter Tiebreaker ist <strong>Strategischer Impact</strong> absteigend, danach Name A\u2192Z, damit das Ergebnis deterministisch und reproduzierbar ist.",
8066
+ "method.s5.ranking": "<strong>Reihenfolge innerhalb der Warteschlange.</strong> Initiativen werden zuerst nach Kategorie gruppiert, in der oben aufgef\xFChrten Reihenfolge (wie auf der Priorisierungsseite), dann innerhalb jeder Kategorie nach <strong>Value</strong>-Score absteigend geordnet, dann \u2014 wenn die Value-at-Stake-Gewichtung in den Einstellungen aktiv ist und die Zeile in Quick Wins / Strategische Plattform-Initiativen liegt \u2014 nach Jahr-3-Nutzen absteigend. Letzter Tiebreaker ist <strong>Strategischer Impact</strong> absteigend, danach Name A\u2192Z, damit das Ergebnis deterministisch und reproduzierbar ist.",
7934
8067
  "method.s10.p7": "<strong>Quick-Win-Definition.</strong> Die Kategorie Quick Wins setzt schnelle Zeit-zum-Wert voraus. Ein Quick Win, der von einem aktiven, nicht-Quick-Win-en Vorgelagerten abh\xE4ngt (Strategische Plattform-Initiative, Betriebsmodell-Modernisierung, Hohes Compliance-Risiko etc.), wird daher automatisch aus den Quick Wins demotet \u2014 der Vorlauf macht ihn nicht mehr schnell. Die Regel ist transitiv: H\xE4ngt A von B ab und wird B demotet, wird A in der n\xE4chsten Iteration ebenfalls demotet.",
7935
8068
  "method.audit.scope.governance": "<strong>Status</strong> und die vier <strong>Bewertungsdimensions-Scores</strong> (Wert, Liefer-Machbarkeit, Compliance &amp; Betriebsrisiko, Strategischer Impact) mit ihrer Konfidenz.",
7936
8069
  "method.audit.scope.metadata": "<strong>Alle Kern-Metadatenfelder</strong> \u2014 Name, Gesch\xE4ftseinheit, Verantwortliche, Beschreibung, Zeitplan, Budget, Anbieterstrategie, L\xF6sungstyp, Digital-Kategorie und Tags.",
@@ -7982,11 +8115,17 @@ var EN_INNOVATION = {
7982
8115
  "subHelp.dataAvailability": "How much evidence (data, prior art, prototypes) already exists to support the idea.",
7983
8116
  "subHelp.dataQuality": "Strength of that evidence \u2014 rigour, sample size, independence, recency.",
7984
8117
  "dim.feasibility.band1.meaning": "Concept, capability or partner gaps make delivery uncertain.",
7985
- "govBand.Elevated.desc": "41\u201360 \xB7 Gated trial \u2014 standard stage-gate controls",
8118
+ "govBand.Low.desc": "0\u201320 \xB7 Minimal oversight \u2014 routine stage-gate checkpoints",
8119
+ "govBand.Moderate.desc": "21\u201340 \xB7 Monitored trial \u2014 standard stage-gate controls",
8120
+ "govBand.Elevated.desc": "41\u201360 \xB7 Active stewardship required \u2014 stop-loss thresholds and capital limits",
8121
+ "govBand.High.desc": "61\u201380 \xB7 Bounded pilot only \u2014 named sponsor and explicit kill criteria",
8122
+ "govBand.Critical.desc": "81\u2013100 \xB7 Board-level sponsorship required \u2014 treat as material strategic risk",
7986
8123
  "govLabel.Controlled Automation": "Monitored Trial",
7987
8124
  "govLabel.Human-in-the-Loop Required": "Active Stewardship Required",
7988
8125
  "govLabel.Restricted Deployment": "Bounded Pilot Only",
7989
8126
  "memo.governance.intro": "{count} initiatives sit in the Bounded Pilot Only band or above (governance \u2265 61/100) and require active board-level monitoring.",
8127
+ "settings.guardrails.maxHighGovernanceSharePct.hint": "At most this share of active initiatives may carry a governance score above 60 (Bounded Pilot Only or higher).",
8128
+ "governance.warning.body": "{count} initiatives require board-level visibility and active risk mitigation due to scores in the Board-Level Sponsorship Required band.",
7990
8129
  "govLabel.High Governance Sensitivity": "Board-Level Sponsorship Required",
7991
8130
  "subHelp.modelRobustness": "How well the core concept holds up under stress, edge cases and pessimistic assumptions.",
7992
8131
  "subHelp.reproducibility": "Likelihood that observed results would repeat under independent conditions.",
@@ -8014,7 +8153,7 @@ var EN_INNOVATION = {
8014
8153
  "settings.prio.longTermBets": "Long Horizons (H3)",
8015
8154
  "settings.prio.incremental": "Incremental Refinements",
8016
8155
  "settings.prio.operatingModel": "New Operating Models",
8017
- "settings.prio.subtitle": "Thresholds used by the Prioritisation page to assign each innovation initiative to a strategic archetype. Rules are evaluated top-to-bottom and the first match wins. All values are scores out of 100 across the four dimensions: V = Value Potential, E = Validation & Evidence, U = Governance & Uncertainty, S = Strategic Impact.",
8156
+ "settings.prio.subtitle": "Thresholds used by the Prioritisation page to assign each innovation initiative to a strategic archetype. Rules are listed in funding order, as on the Prioritisation page; each initiative is assigned by the first rule it matches, checked in the order of its precedence number. All values are scores out of 100 across the four dimensions: V = Value Potential, E = Validation & Evidence, U = Governance & Uncertainty, S = Strategic Impact.",
8018
8157
  "inventory.col.scores": "Scores (V/E/U/S)",
8019
8158
  "concept.eyebrow": "Steering of AI, digital and transformation portfolios",
8020
8159
  "concept.title": "Turn scattered experiments into a managed innovation portfolio.",
@@ -8082,11 +8221,11 @@ var EN_INNOVATION = {
8082
8221
  "method.s2.title": "2. Governance & Uncertainty Classification",
8083
8222
  "method.s2.subtitle": "Uncertainty bands and what they imply for stage-gate posture and stop-loss controls.",
8084
8223
  "method.s2.intro": "Initiatives are classified into bands based on the Governance & Uncertainty score:",
8085
- "method.s2.b1": "<strong>0\u201320 \xB7 Low uncertainty</strong>: routine stage-gate checkpoints; no escalation required.",
8086
- "method.s2.b2": "<strong>21\u201340 \xB7 Gated trial</strong>: standard stage-gate controls and progress monitoring.",
8087
- "method.s2.b3": "<strong>41\u201360 \xB7 Tight stage-gating</strong>: explicit stop-loss thresholds and capital limits.",
8088
- "method.s2.b4": "<strong>61\u201380 \xB7 Board sponsorship required</strong>: active board-level oversight, named sponsor and explicit kill criteria.",
8089
- "method.s2.b5": "<strong>81\u2013100 \xB7 High strategic exposure</strong>: treat as material strategic risk; pursue only with explicit ringfencing and continuous oversight.",
8224
+ "method.s2.b1": "<strong>0\u201320 \xB7 Minimal oversight</strong>: routine stage-gate checkpoints; no escalation required.",
8225
+ "method.s2.b2": "<strong>21\u201340 \xB7 Monitored trial</strong>: standard stage-gate controls and progress monitoring.",
8226
+ "method.s2.b3": "<strong>41\u201360 \xB7 Active stewardship required</strong>: tight stage-gating with explicit stop-loss thresholds and capital limits.",
8227
+ "method.s2.b4": "<strong>61\u201380 \xB7 Bounded pilot only</strong>: active board-level oversight, named sponsor and explicit kill criteria.",
8228
+ "method.s2.b5": "<strong>81\u2013100 \xB7 Board-level sponsorship required</strong>: treat as material strategic risk; pursue only with explicit ringfencing and continuous oversight.",
8090
8229
  "method.s4.subtitle": "How each initiative is positioned on the Business Impact \xD7 Validation plane.",
8091
8230
  "method.s4.intro": "The x-axis (<strong>Business Impact</strong>) is the equal-weighted average of Value Potential and Strategic Impact: <code>BusinessImpact = (Value + Strategic) / 2</code>. The y-axis is Validation & Evidence. Quadrants are split deterministically at 50 on both axes:",
8092
8231
  "method.s4.scale": "<strong>Scale</strong> \u2014 Business Impact \u2265 50 and Validation \u2265 50. High impact, strong evidence \u2014 ready to scale.",
@@ -8096,7 +8235,7 @@ var EN_INNOVATION = {
8096
8235
  "method.s4.bubbles": "Bubble size additionally emphasises Strategic Impact on its own (so a strategic bet reads as a larger bubble even when its value score is moderate); bubble colour reflects the uncertainty band.",
8097
8236
  "method.s5.governance": "<strong>High-Uncertainty Bets</strong> (precedence 3) \u2014 governance & uncertainty score \u2265 {g} (and the bet was not already classified as Quick Wins or Strategic Core). Elevated strategic, market or execution uncertainty that must be de-risked through stage-gating before scaling.",
8098
8237
  "memo.assumptions.signals": "No external regulatory, peer-review or third-party assurance signals have been incorporated into these scores.",
8099
- "method.s6.p1": 'The <a href="https://www.investopedia.com/terms/h/hhi.asp" target="_blank" rel="noopener noreferrer" class="text-primary underline underline-offset-2 hover:no-underline">Herfindahl\u2013Hirschman Index</a> is applied to four cuts of the portfolio: <strong>partner strategy</strong>, <strong>bet type</strong>, <strong>innovation category</strong>, and <strong>business unit</strong>.',
8238
+ "method.s6.p1": 'The <a href="https://www.investopedia.com/terms/h/hhi.asp" target="_blank" rel="noopener noreferrer" class="text-primary underline underline-offset-2 hover:no-underline">Herfindahl\u2013Hirschman Index</a> is applied to four cuts on the Concentration page: <strong>partner strategy</strong>, <strong>innovation category</strong>, <strong>business unit</strong> and <strong>uncertainty band</strong>. The board pack uses partner, category, business unit and bet type, plus a weighted HHI.',
8100
8239
  "method.s6.p2": "A business-unit \xD7 innovation-category cluster heatmap on the Concentration page surfaces specific over-exposed combinations beyond the aggregate.",
8101
8240
  "concept.problem.p1": "Many organisations are pursuing innovation bets across a wide range of horizons. These initiatives often emerge from local experimentation within business units, labs or partner ecosystems rather than from a structured strategic process.",
8102
8241
  "concept.dim.value.body": "Strategic and economic potential of the innovation bet. Bets that target large, growing or under-served opportunities typically offer the greatest upside; narrow-scale or marginal-efficiency bets rarely justify the organisational effort required.",
@@ -8123,7 +8262,11 @@ var EN_INNOVATION = {
8123
8262
  "filters.vendor.open": "Open / internal",
8124
8263
  "concentration.hhi.vendor": "Partner strategy",
8125
8264
  "concentration.vendor.title": "Partner dependency",
8126
- "concentration.vendor.subtitle": "Number of bets by partner strategy. Click a bar to view the list.",
8265
+ "concentration.vendor.subtitle": "Bets split by stage, ordered by lock-in. Click a segment to view the list.",
8266
+ "concentration.measure.count": "Bets",
8267
+ "concentration.tooltip.count": "Bets",
8268
+ "concentration.takeaway.count": "{name}: {value} of {total} bets ({share} %), {prod} already in production.",
8269
+ "concentration.takeaway.noBudget": "No budget recorded for the bets in scope.",
8127
8270
  "concentration.obs.vendor": "High partner concentration. The portfolio is materially dependent on a narrow set of external partners; consider broadening the ecosystem to reduce systemic dependency.",
8128
8271
  "memo.concentration.vendor": "Partner strategy concentration: {name} accounts for {count} of {total} bets ({pct}%).",
8129
8272
  "memo.opmodel.vendor": "Partner strategy: {name} should be reviewed against ecosystem-resilience standards; over-reliance on a single partner increases systemic fragility.",
@@ -8146,17 +8289,13 @@ var EN_INNOVATION = {
8146
8289
  "dim.feasibility.band2.meaning": "Promising but requires further evidence, prototypes or partner capability.",
8147
8290
  "dim.feasibility.band3.label": "Ready to scale",
8148
8291
  "dim.feasibility.band3.meaning": "Evidence, capability and a credible path to scale are in place.",
8149
- "dim.governance.band1.label": "Low uncertainty",
8150
8292
  "dim.governance.band1.meaning": "Routine stage-gate checkpoints; no escalation required.",
8151
- "dim.governance.band2.label": "Gated trial",
8152
8293
  "dim.governance.band2.meaning": "Standard stage-gate controls and progress monitoring required.",
8153
- "dim.governance.band3.label": "Tight stage-gating",
8154
- "dim.governance.band3.meaning": "Active board-level oversight, stop-loss thresholds and capital limits required.",
8155
- "dim.governance.band4.label": "High strategic exposure",
8156
- "dim.governance.band4.meaning": "Treat as material strategic risk; pursue only with explicit ringfencing and continuous oversight.",
8157
- "dim.strategic.band1.label": "Incremental",
8294
+ "dim.governance.band3.meaning": "Tight stage-gating with explicit stop-loss thresholds and capital limits required.",
8295
+ "dim.governance.band4.meaning": "Active board-level oversight, a named sponsor and explicit kill criteria required.",
8296
+ "dim.governance.band5.meaning": "Treat as material strategic risk; pursue only with explicit ringfencing and continuous oversight.",
8158
8297
  "dim.strategic.band1.meaning": "Refines an existing offering only.",
8159
- "dim.strategic.band3.meaning": "Opens new operating models, revenue streams or market positioning.",
8298
+ "dim.strategic.band5.meaning": "Opens new revenue streams or a structural market position.",
8160
8299
  "op.governance.detailLow": "Embedded delivery teams with part-time stage-gate coverage are typically sufficient at this load.",
8161
8300
  "boardPack.col.f": "E",
8162
8301
  "boardPack.col.g": "U",
@@ -8181,11 +8320,6 @@ var EN_INNOVATION = {
8181
8320
  "concept.features.f24.body": "Self-contained demo portfolios per mode (AI / Digital / Innovation) load with realistic initiatives and dependencies \u2014 so new users can explore every view immediately without entering data.",
8182
8321
  "concept.features.f29.body": "Run the console as a multi-tenant SaaS: each organisation is an isolated tenant with its own portfolio and data. Members sign in through managed authentication and get role-based access \u2014 admin, member or viewer \u2014 refined by granular per-section permissions an admin grants from Settings, enforced on both the server and the UI. Every governance-critical and Core Metadata change is captured in a per-field audit trail with the acting user and a timestamp, and each initiative shows who created and last edited it. Cloud sync keeps the shared portfolio consistent across the team, while local (no-account) mode still works for a single user. Privileged admin actions \u2014 access grants, role and permission changes, settings, profile and initiative changes \u2014 are additionally recorded in an organisation-level admin activity log in Settings.",
8183
8322
  "concept.features.f30.body": "A rules-based, severity-ranked list of the decisions the portfolio's own data calls for: stop/defer candidates, gate discipline, capacity and budget shortfalls, and concentration. Benefits-realisation rules flag production systems that under-deliver \u2014 or never measure \u2014 their promised value. Board-set guardrails add the red lines: admins define policy limits in Settings \u2014 a budget-concentration cap per business unit, a value floor for funded initiatives and an uncertainty-load ceiling \u2014 each showing a live pass/fail, and every breach lands here as a decide-now item.",
8184
- "method.rules.r1.formula": "Value \xD7 Validation \u2192 Portfolio shape",
8185
- "method.rules.r1.explanation": "Quadrant placement on the Value \xD7 Validation map drives the go / scale / pilot / stop decision for each initiative.",
8186
- "method.rules.r2.formula": "Uncertainty Band \u2192 Veto criterion",
8187
- "method.rules.r2.explanation": "Any initiative above the restricted band (Governance & Uncertainty \u2265 61) cannot scale until explicit board-level controls are in place; it is removed from the prioritised list regardless of value or validation.",
8188
- "method.rules.r4.explanation": "If any portfolio cut (partner, solution type, innovation category, or business unit) exceeds HHI 0.25 on the normalised 0\u20131 scale, the portfolio steward must actively consider redistribution before approving new initiatives in the dominant segment.",
8189
8323
  "method.s1.dimensions.value": "<strong>Value Potential</strong> \u2014 economic and strategic upside.",
8190
8324
  "method.s1.dimensions.feasibility": "<strong>Validation &amp; Evidence</strong> \u2014 strength, rigour and repeatability of the evidence.",
8191
8325
  "method.s1.dimensions.governance": "<strong>Governance &amp; Uncertainty</strong> \u2014 stage-gate posture and uncertainty load (deep dive in \xA7 3).",
@@ -8196,7 +8330,7 @@ var EN_INNOVATION = {
8196
8330
  "method.s5.longTerm": "<strong>Long Horizons (H3)</strong> (precedence 4) \u2014 value \u2265 {v}, validation &lt; {f}, and strategic \u2265 {s} (after High-Uncertainty Bets has already claimed initiatives above its threshold). Strategically attractive but not yet validated \u2014 keep on the horizon.",
8197
8331
  "method.s5.incremental": "<strong>Incremental Refinements</strong> (precedence 5) \u2014 value &lt; {v}, validation \u2265 {f}, and strategic &lt; {s}. Easy to ship but limited upside; useful as fillers.",
8198
8332
  "method.s5.uncategorised": "<strong>Unsorted Experiments</strong> (precedence 7) \u2014 fallback for initiatives that don't satisfy any of rules 1\u20136. Treat as exploratory until scores sharpen.",
8199
- "method.s5.ranking": "<strong>Ranking inside the queue.</strong> Initiatives are first grouped by the category rules above (precedence 1 \u2192 7), then within each category ordered by <strong>Value Potential</strong> score descending, then \u2014 if Value-at-Stake weighting is enabled in Settings and the row sits in Easy Experiments / Scale Candidates \u2014 Year-3 benefit descending. Final tie-break is <strong>Strategic Impact</strong> descending, then name A\u2192Z, so the result is deterministic and reproducible.",
8333
+ "method.s5.ranking": "<strong>Ranking inside the queue.</strong> Initiatives are first grouped by category in the order listed above (the order the Prioritisation page shows them), then within each category ordered by <strong>Value Potential</strong> score descending, then \u2014 if Value-at-Stake weighting is enabled in Settings and the row sits in Easy Experiments / Scale Candidates \u2014 Year-3 benefit descending. Final tie-break is <strong>Strategic Impact</strong> descending, then name A\u2192Z, so the result is deterministic and reproducible.",
8200
8334
  "method.s10.p7": "<strong>Easy Experiment definition.</strong> The Easy Experiments category requires fast time-to-value. Therefore an Easy Experiment that depends on an active upstream outside Easy Experiments (Scale Candidate, New Operating Models, High-Uncertainty Bets etc.) is automatically demoted out of Easy Experiments \u2014 the upstream's pre-work makes it no longer quick. The rule is transitive: if A depends on B, and B is itself demoted, A is also demoted in the next iteration.",
8201
8335
  "method.audit.scope.governance": "<strong>Status</strong> and the four <strong>evaluation dimension scores</strong> (Value Potential, Validation &amp; Evidence, Governance &amp; Uncertainty, Strategic Impact) with their confidence.",
8202
8336
  "method.audit.scope.metadata": "<strong>All Core Metadata fields</strong> \u2014 name, business unit, owner, description, timeline, budget, partner strategy, solution type, innovation category and tags.",
@@ -8248,11 +8382,17 @@ var DE_INNOVATION = {
8248
8382
  "subHelp.dataAvailability": "Wie viel Evidenz (Daten, Stand der Technik, Prototypen) die Idee bereits st\xFCtzt.",
8249
8383
  "subHelp.dataQuality": "Belastbarkeit dieser Evidenz \u2014 Rigorosit\xE4t, Stichprobengr\xF6sse, Unabh\xE4ngigkeit, Aktualit\xE4t.",
8250
8384
  "dim.feasibility.band1.meaning": "L\xFCcken bei Konzept, F\xE4higkeiten oder Partnern machen die Umsetzung unsicher.",
8251
- "govBand.Elevated.desc": "41\u201360 \xB7 Gegateter Pilot \u2014 Standard-Stage-Gate-Kontrollen",
8385
+ "govBand.Low.desc": "0\u201320 \xB7 Minimale Aufsicht \u2014 Routine-Stage-Gate-Checkpoints",
8386
+ "govBand.Moderate.desc": "21\u201340 \xB7 \xDCberwachte Erprobung \u2014 Standard-Stage-Gate-Kontrollen",
8387
+ "govBand.Elevated.desc": "41\u201360 \xB7 Aktive Begleitung erforderlich \u2014 Stop-Loss-Schwellen und Kapitalgrenzen",
8388
+ "govBand.High.desc": "61\u201380 \xB7 Nur eingegrenzter Pilot \u2014 benannter Sponsor und explizite Kill-Kriterien",
8389
+ "govBand.Critical.desc": "81\u2013100 \xB7 Vorstandspatenschaft erforderlich \u2014 als wesentliches strategisches Risiko behandeln",
8252
8390
  "govLabel.Controlled Automation": "\xDCberwachte Erprobung",
8253
8391
  "govLabel.Human-in-the-Loop Required": "Aktive Begleitung erforderlich",
8254
8392
  "govLabel.Restricted Deployment": "Nur eingegrenzter Pilot",
8255
8393
  "memo.governance.intro": "{count} Initiativen liegen im Band \u201ENur eingegrenzter Pilot\u201C oder dar\xFCber (Governance \u2265 61/100) und ben\xF6tigen aktive Vorstandsaufsicht.",
8394
+ "settings.guardrails.maxHighGovernanceSharePct.hint": "H\xF6chstens dieser Anteil der aktiven Initiativen darf einen Governance-Score \xFCber 60 tragen (Nur eingegrenzter Pilot oder h\xF6her).",
8395
+ "governance.warning.body": "{count} Initiativen ben\xF6tigen aufgrund von Werten im Band \u201EVorstandspatenschaft erforderlich\u201C Vorstandsaufmerksamkeit und aktive Risikominderung.",
8256
8396
  "govLabel.High Governance Sensitivity": "Vorstandspatenschaft erforderlich",
8257
8397
  "subHelp.modelRobustness": "Wie gut das Kernkonzept Belastung, Edge-Cases und pessimistische Annahmen aush\xE4lt.",
8258
8398
  "subHelp.reproducibility": "Wahrscheinlichkeit, dass beobachtete Ergebnisse unter unabh\xE4ngigen Bedingungen wiederholbar sind.",
@@ -8280,7 +8420,7 @@ var DE_INNOVATION = {
8280
8420
  "settings.prio.longTermBets": "Lange Horizonte (H3)",
8281
8421
  "settings.prio.incremental": "Inkrementelle Verfeinerungen",
8282
8422
  "settings.prio.operatingModel": "Neue Betriebsmodelle",
8283
- "settings.prio.subtitle": "Schwellenwerte, mit denen die Priorisierungsseite jede Innovationsinitiative einem strategischen Archetyp zuordnet. Die Regeln werden von oben nach unten gepr\xFCft, die erste \xDCbereinstimmung gewinnt. Alle Werte sind Punkte von 0\u2013100 \xFCber die vier Dimensionen: W = Wertpotenzial, E = Validierung & Evidenz, U = Governance & Unsicherheit, S = Strategischer Impact.",
8423
+ "settings.prio.subtitle": "Schwellenwerte, mit denen die Priorisierungsseite jede Innovationsinitiative einem strategischen Archetyp zuordnet. Die Regeln stehen in F\xF6rderreihenfolge wie auf der Priorisierungsseite; jede Initiative wird der ersten Regel zugeordnet, die sie erf\xFCllt, gepr\xFCft in der Reihenfolge der Pr\xE4zedenznummer. Alle Werte sind Punkte von 0\u2013100 \xFCber die vier Dimensionen: W = Wertpotenzial, E = Validierung & Evidenz, U = Governance & Unsicherheit, S = Strategischer Impact.",
8284
8424
  "inventory.col.scores": "Punkte (W/E/U/S)",
8285
8425
  "concept.eyebrow": "Steuerung von KI-, Digital- und Transformationsportfolios",
8286
8426
  "concept.title": "Verstreute Experimente in ein gesteuertes Innovationsportfolio \xFCberf\xFChren.",
@@ -8348,11 +8488,11 @@ var DE_INNOVATION = {
8348
8488
  "method.s2.title": "2. Governance- & Unsicherheits-Klassifikation",
8349
8489
  "method.s2.subtitle": "Unsicherheits-B\xE4nder und was sie f\xFCr Stage-Gate-Haltung und Stop-Loss-Kontrollen bedeuten.",
8350
8490
  "method.s2.intro": "Initiativen werden auf Basis des Governance- & Unsicherheits-Werts klassifiziert:",
8351
- "method.s2.b1": "<strong>0\u201320 \xB7 Geringe Unsicherheit</strong>: Routine-Stage-Gate-Checkpoints; keine Eskalation erforderlich.",
8352
- "method.s2.b2": "<strong>21\u201340 \xB7 Gated Trial</strong>: Standard-Stage-Gate-Kontrollen und Fortschrittsmonitoring.",
8353
- "method.s2.b3": "<strong>41\u201360 \xB7 Strenges Stage-Gating</strong>: explizite Stop-Loss-Schwellen und Kapitalgrenzen.",
8354
- "method.s2.b4": "<strong>61\u201380 \xB7 Vorstandspatenschaft erforderlich</strong>: aktive Vorstandsaufsicht, benannter Sponsor und explizite Kill-Kriterien.",
8355
- "method.s2.b5": "<strong>81\u2013100 \xB7 Hohe strategische Exposition</strong>: als wesentliches strategisches Risiko behandeln; nur mit Ringfencing und kontinuierlicher Aufsicht verfolgen.",
8491
+ "method.s2.b1": "<strong>0\u201320 \xB7 Minimale Aufsicht</strong>: Routine-Stage-Gate-Checkpoints; keine Eskalation erforderlich.",
8492
+ "method.s2.b2": "<strong>21\u201340 \xB7 \xDCberwachte Erprobung</strong>: Standard-Stage-Gate-Kontrollen und Fortschrittsmonitoring.",
8493
+ "method.s2.b3": "<strong>41\u201360 \xB7 Aktive Begleitung erforderlich</strong>: strenges Stage-Gating mit expliziten Stop-Loss-Schwellen und Kapitalgrenzen.",
8494
+ "method.s2.b4": "<strong>61\u201380 \xB7 Nur eingegrenzter Pilot</strong>: aktive Vorstandsaufsicht, benannter Sponsor und explizite Kill-Kriterien.",
8495
+ "method.s2.b5": "<strong>81\u2013100 \xB7 Vorstandspatenschaft erforderlich</strong>: als wesentliches strategisches Risiko behandeln; nur mit Ringfencing und kontinuierlicher Aufsicht verfolgen.",
8356
8496
  "method.s4.subtitle": "Wie jede Initiative auf der Business-Impact-\xD7-Validierung-Ebene positioniert wird.",
8357
8497
  "method.s4.intro": "Die x-Achse (<strong>Business Impact</strong>) ist der gleichgewichtete Mittelwert aus Wertpotenzial und strategischem Impact: <code>BusinessImpact = (Wert + Strategisch) / 2</code>. Die y-Achse ist Validierung & Evidenz. Die Quadranten werden deterministisch bei 50 auf beiden Achsen geteilt:",
8358
8498
  "method.s4.scale": "<strong>Skalieren</strong> \u2014 Business Impact \u2265 50 und Validierung \u2265 50. Hoher Impact, starke Evidenz \u2014 bereit zur Skalierung.",
@@ -8362,7 +8502,7 @@ var DE_INNOVATION = {
8362
8502
  "method.s4.bubbles": "Die Blasengr\xF6sse betont zus\xE4tzlich den strategischen Impact f\xFCr sich (eine strategische Wette erscheint also gr\xF6sser, selbst wenn ihr Wert-Score moderat ist); die Farbe spiegelt das Unsicherheits-Band wider.",
8363
8503
  "method.s5.governance": "<strong>Hochunsichere Wetten</strong> (Pr\xE4zedenz 3) \u2014 Governance- & Unsicherheits-Wert \u2265 {g} (und die Wette wurde nicht bereits als Quick Wins oder Strategische Kernwette klassifiziert). Erh\xF6hte strategische, Markt- oder Ausf\xFChrungsunsicherheit, die vor einer Skalierung durch Stage-Gating reduziert werden muss.",
8364
8504
  "memo.assumptions.signals": "Es wurden keine externen regulatorischen, Peer-Review- oder Drittparteien-Signale in diese Scores einbezogen.",
8365
- "method.s6.p1": 'Der <a href="https://www.investopedia.com/terms/h/hhi.asp" target="_blank" rel="noopener noreferrer" class="text-primary underline underline-offset-2 hover:no-underline">Herfindahl\u2013Hirschman-Index</a> wird auf vier Schnitte angewendet: <strong>Partnerstrategie</strong>, <strong>Wettentyp</strong>, <strong>Innovations-Kategorie</strong> und <strong>Gesch\xE4ftseinheit</strong>.',
8505
+ "method.s6.p1": 'Der <a href="https://www.investopedia.com/terms/h/hhi.asp" target="_blank" rel="noopener noreferrer" class="text-primary underline underline-offset-2 hover:no-underline">Herfindahl\u2013Hirschman-Index</a> wird auf vier Schnitte der Konzentrationsseite angewendet: <strong>Partnerstrategie</strong>, <strong>Innovations-Kategorie</strong>, <strong>Gesch\xE4ftseinheit</strong> und <strong>Unsicherheits-Band</strong>. Das Board-Pack verwendet Partner, Kategorie, Gesch\xE4ftseinheit und Wettentyp sowie einen gewichteten HHI.',
8366
8506
  "method.s6.p2": "Eine Gesch\xE4ftseinheit-\xD7-Innovations-Kategorie-Heatmap auf der Konzentrations-Seite deckt dar\xFCber hinaus spezifische \xFCberexponierte Kombinationen jenseits des Aggregats auf.",
8367
8507
  "concept.problem.p1": "Viele Organisationen verfolgen Innovationswetten \xFCber unterschiedliche Horizonte hinweg. Diese Initiativen entstehen h\xE4ufig aus lokalen Experimenten in Gesch\xE4ftseinheiten, Labs oder Partner-\xD6kosystemen \u2013 nicht aus einem strukturierten strategischen Prozess.",
8368
8508
  "concept.dim.value.body": "Strategisches und \xF6konomisches Potenzial der Innovationswette. Wetten auf grosse, wachsende oder unterversorgte Chancen bieten das gr\xF6sste Upside; Wetten mit begrenztem Volumen oder marginalen Effizienzgewinnen rechtfertigen den organisatorischen Aufwand selten.",
@@ -8389,7 +8529,11 @@ var DE_INNOVATION = {
8389
8529
  "filters.vendor.open": "Offen / intern",
8390
8530
  "concentration.hhi.vendor": "Partnerstrategie",
8391
8531
  "concentration.vendor.title": "Partner-Abh\xE4ngigkeit",
8392
- "concentration.vendor.subtitle": "Anzahl Wetten nach Partnerstrategie. Auf einen Balken klicken, um die Liste anzuzeigen.",
8532
+ "concentration.vendor.subtitle": "Wetten nach Phase aufgeteilt, nach Lock-in geordnet. Segment anklicken, um die Liste anzuzeigen.",
8533
+ "concentration.measure.count": "Wetten",
8534
+ "concentration.tooltip.count": "Wetten",
8535
+ "concentration.takeaway.count": "{name}: {value} von {total} Wetten ({share} %), {prod} davon bereits in Produktion.",
8536
+ "concentration.takeaway.noBudget": "F\xFCr die Wetten im Fokus ist kein Budget erfasst.",
8393
8537
  "concentration.obs.vendor": "Hohe Partnerkonzentration. Das Portfolio h\xE4ngt wesentlich von wenigen externen Partnern ab; eine Verbreiterung des \xD6kosystems reduziert die systemische Abh\xE4ngigkeit.",
8394
8538
  "memo.concentration.vendor": "Partnerstrategie-Konzentration: {name} steht f\xFCr {count} von {total} Wetten ({pct} %).",
8395
8539
  "memo.opmodel.vendor": "Partnerstrategie: {name} sollte gegen Standards der \xD6kosystem-Resilienz gepr\xFCft werden; zu starke Abh\xE4ngigkeit von einem Partner erh\xF6ht die systemische Fragilit\xE4t.",
@@ -8412,17 +8556,13 @@ var DE_INNOVATION = {
8412
8556
  "dim.feasibility.band2.meaning": "Vielversprechend, erfordert aber weitere Evidenz, Prototypen oder Partnerf\xE4higkeit.",
8413
8557
  "dim.feasibility.band3.label": "Bereit zur Skalierung",
8414
8558
  "dim.feasibility.band3.meaning": "Evidenz, F\xE4higkeit und ein glaubw\xFCrdiger Skalierungspfad sind vorhanden.",
8415
- "dim.governance.band1.label": "Geringe Unsicherheit",
8416
8559
  "dim.governance.band1.meaning": "Routinem\xE4ssige Stage-Gate-Checkpoints; keine Eskalation erforderlich.",
8417
- "dim.governance.band2.label": "Gegateter Pilot",
8418
- "dim.governance.band2.meaning": "Standard Stage-Gate-Kontrollen und Fortschrittsmonitoring erforderlich.",
8419
- "dim.governance.band3.label": "Enges Stage-Gating",
8420
- "dim.governance.band3.meaning": "Aktive Vorstandsaufsicht, Stop-Loss-Schwellen und Kapitallimits erforderlich.",
8421
- "dim.governance.band4.label": "Hohe strategische Exposition",
8422
- "dim.governance.band4.meaning": "Als materielles strategisches Risiko behandeln; nur mit explizitem Ringfencing und kontinuierlicher Aufsicht verfolgen.",
8423
- "dim.strategic.band1.label": "Inkrementell",
8560
+ "dim.governance.band2.meaning": "Standard-Stage-Gate-Kontrollen und Fortschrittsmonitoring erforderlich.",
8561
+ "dim.governance.band3.meaning": "Strenges Stage-Gating mit expliziten Stop-Loss-Schwellen und Kapitalgrenzen erforderlich.",
8562
+ "dim.governance.band4.meaning": "Aktive Vorstandsaufsicht, benannter Sponsor und explizite Kill-Kriterien erforderlich.",
8563
+ "dim.governance.band5.meaning": "Als wesentliches strategisches Risiko behandeln; nur mit explizitem Ringfencing und kontinuierlicher Aufsicht verfolgen.",
8424
8564
  "dim.strategic.band1.meaning": "Verfeinert nur ein bestehendes Angebot.",
8425
- "dim.strategic.band3.meaning": "Er\xF6ffnet neue Betriebsmodelle, Erl\xF6sstr\xF6me oder Marktpositionierungen.",
8565
+ "dim.strategic.band5.meaning": "Er\xF6ffnet neue Erl\xF6sstr\xF6me oder eine strukturelle Marktposition.",
8426
8566
  "op.governance.detailLow": "Eingebettete Teams mit teilweiser Stage-Gate-Abdeckung reichen bei dieser Last meist aus.",
8427
8567
  "boardPack.col.f": "E",
8428
8568
  "boardPack.col.g": "U",
@@ -8447,11 +8587,6 @@ var DE_INNOVATION = {
8447
8587
  "concept.features.f24.body": "In sich geschlossene Demo-Portfolios pro Modus (KI / Digital / Innovation) laden mit realistischen Initiativen und Abh\xE4ngigkeiten \u2014 sodass neue Nutzer jede Sicht sofort erkunden k\xF6nnen, ohne Daten einzugeben.",
8448
8588
  "concept.features.f29.body": "Die Konsole l\xE4uft als mandantenf\xE4hige SaaS: Jede Organisation ist ein isolierter Mandant mit eigenem Portfolio und eigenen Daten. Mitglieder melden sich \xFCber eine verwaltete Authentifizierung an und erhalten rollenbasierten Zugriff \u2014 Admin, Mitglied oder Betrachter \u2014 verfeinert durch granulare Berechtigungen pro Bereich, die ein Admin in den Einstellungen vergibt und die serverseitig wie auch in der Oberfl\xE4che durchgesetzt werden. Jede governance-kritische und Kern-Metadaten-\xC4nderung wird in einem feldgenauen Audit-Trail mit handelndem Benutzer und Zeitstempel erfasst, und jede Initiative zeigt, wer sie erstellt und zuletzt bearbeitet hat. Cloud-Sync h\xE4lt das gemeinsame Portfolio im Team konsistent, w\xE4hrend der lokale Modus (ohne Konto) weiterhin f\xFCr einen einzelnen Nutzer funktioniert. Privilegierte Admin-Aktionen \u2014 Zugriffsvergaben, Rollen- und Rechte\xE4nderungen, \xC4nderungen an Einstellungen, Profilen und Initiativen \u2014 werden zus\xE4tzlich in einem Admin-Aktivit\xE4tsprotokoll auf Organisationsebene in den Einstellungen erfasst.",
8449
8589
  "concept.features.f30.body": "Eine regelbasierte, nach Dringlichkeit sortierte Liste der Entscheidungen, die die Portfoliodaten selbst einfordern: Stopp-/Aufschub-Kandidaten, Gate-Disziplin, Kapazit\xE4ts- und Budgetengp\xE4sse sowie Konzentration. Nutzenrealisierungs-Regeln markieren Produktionssysteme, die ihren zugesagten Nutzen verfehlen \u2014 oder nie messen. Vom Board gesetzte Leitplanken erg\xE4nzen die roten Linien: Admins definieren Richtwerte in den Einstellungen \u2014 Budgetkonzentrations-Obergrenze je Gesch\xE4ftsbereich, Wert-Untergrenze f\xFCr finanzierte Initiativen und Unsicherheitslast-Obergrenze \u2014 jeweils mit Live-Pr\xFCfung, und jeder Verstoss erscheint hier als Entscheidungspunkt.",
8450
- "method.rules.r1.formula": "Nutzen \xD7 Validierung \u2192 Portfolio-Gestalt",
8451
- "method.rules.r1.explanation": "Die Quadrantenposition auf der Nutzen-\xD7-Validierungs-Karte bestimmt die Go-/Skalieren-/Pilot-/Stopp-Entscheidung f\xFCr jede Initiative.",
8452
- "method.rules.r2.formula": "Unsicherheits-Band \u2192 Veto-Kriterium",
8453
- "method.rules.r2.explanation": "Jede Initiative oberhalb des Restricted-Bands (Governance & Unsicherheit \u2265 61) darf nicht skaliert werden, solange keine expliziten Vorstandskontrollen vorhanden sind; sie wird unabh\xE4ngig von Nutzen oder Validierung von der Priorisierungsliste entfernt.",
8454
- "method.rules.r4.explanation": "\xDCbersteigt ein Portfolio-Schnitt (Partner, L\xF6sungstyp, Innovations-Kategorie oder Gesch\xE4ftseinheit) den HHI 0,25 auf der normierten 0\u20131-Skala, muss der Portfolio-Steward eine Umverteilung aktiv pr\xFCfen, bevor neue Initiativen im dominanten Segment freigegeben werden.",
8455
8590
  "method.s1.dimensions.value": "<strong>Wertpotenzial</strong> \u2014 \xF6konomischer und strategischer Nutzen.",
8456
8591
  "method.s1.dimensions.feasibility": "<strong>Validierung &amp; Evidenz</strong> \u2014 St\xE4rke, Strenge und Wiederholbarkeit der Evidenz.",
8457
8592
  "method.s1.dimensions.governance": "<strong>Governance &amp; Unsicherheit</strong> \u2014 Stage-Gate-Haltung und Unsicherheitslast (Vertiefung in \xA7 3).",
@@ -8462,7 +8597,7 @@ var DE_INNOVATION = {
8462
8597
  "method.s5.longTerm": "<strong>Lange Horizonte (H3)</strong> (Pr\xE4zedenz 4) \u2014 Wert \u2265 {v}, Validierung &lt; {f} und Strategie \u2265 {s} (nachdem Hochunsichere Wetten Initiativen oberhalb ihres Schwellenwerts bereits beansprucht haben). Strategisch attraktiv, aber noch nicht validiert \u2014 am Horizont halten.",
8463
8598
  "method.s5.incremental": "<strong>Inkrementelle Verfeinerungen</strong> (Pr\xE4zedenz 5) \u2014 Wert &lt; {v}, Validierung \u2265 {f} und Strategie &lt; {s}. Leicht umsetzbar, aber begrenzter Nutzen; geeignet als F\xFCllinitiativen.",
8464
8599
  "method.s5.uncategorised": "<strong>Unsortierte Experimente</strong> (Pr\xE4zedenz 7) \u2014 Auffangkategorie f\xFCr Initiativen, die keine der Regeln 1\u20136 erf\xFCllen. Bis zur Sch\xE4rfung der Bewertung explorativ behandeln.",
8465
- "method.s5.ranking": "<strong>Reihenfolge innerhalb der Warteschlange.</strong> Initiativen werden zuerst nach den Kategorie-Regeln oben gruppiert (Pr\xE4zedenz 1 \u2192 7), dann innerhalb jeder Kategorie nach <strong>Wertpotenzial</strong>-Score absteigend geordnet, dann \u2014 wenn die Value-at-Stake-Gewichtung in den Einstellungen aktiv ist und die Zeile in Einfache Experimente / Skalierungs-Kandidaten liegt \u2014 nach Jahr-3-Nutzen absteigend. Letzter Tiebreaker ist <strong>Strategischer Impact</strong> absteigend, danach Name A\u2192Z, damit das Ergebnis deterministisch und reproduzierbar ist.",
8600
+ "method.s5.ranking": "<strong>Reihenfolge innerhalb der Warteschlange.</strong> Initiativen werden zuerst nach Kategorie gruppiert, in der oben aufgef\xFChrten Reihenfolge (wie auf der Priorisierungsseite), dann innerhalb jeder Kategorie nach <strong>Wertpotenzial</strong>-Score absteigend geordnet, dann \u2014 wenn die Value-at-Stake-Gewichtung in den Einstellungen aktiv ist und die Zeile in Einfache Experimente / Skalierungs-Kandidaten liegt \u2014 nach Jahr-3-Nutzen absteigend. Letzter Tiebreaker ist <strong>Strategischer Impact</strong> absteigend, danach Name A\u2192Z, damit das Ergebnis deterministisch und reproduzierbar ist.",
8466
8601
  "method.s10.p7": "<strong>Definition Einfaches Experiment.</strong> Die Kategorie Einfache Experimente setzt schnelle Zeit-zum-Wert voraus. Ein Einfaches Experiment, das von einem aktiven Vorgelagerten ausserhalb der Einfachen Experimente abh\xE4ngt (Skalierungs-Kandidat, Neue Betriebsmodelle, Hochunsichere Wetten etc.), wird daher automatisch aus den Einfachen Experimenten demotet \u2014 der Vorlauf macht es nicht mehr schnell. Die Regel ist transitiv: H\xE4ngt A von B ab und wird B demotet, wird A in der n\xE4chsten Iteration ebenfalls demotet.",
8467
8602
  "method.audit.scope.governance": "<strong>Status</strong> und die vier <strong>Bewertungsdimensions-Scores</strong> (Wertpotenzial, Validierung &amp; Evidenz, Governance &amp; Unsicherheit, Strategischer Impact) mit ihrer Konfidenz.",
8468
8603
  "method.audit.scope.metadata": "<strong>Alle Kern-Metadatenfelder</strong> \u2014 Name, Gesch\xE4ftseinheit, Verantwortliche, Beschreibung, Zeitplan, Budget, Partnerstrategie, L\xF6sungstyp, Innovations-Kategorie und Tags.",
@@ -9773,8 +9908,22 @@ var OPTIONAL_SECTIONS = [
9773
9908
  {
9774
9909
  key: "milestones",
9775
9910
  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."
9911
+ en: `[{id?, 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. id? is a label (e.g. "m1") a follow-up's milestoneId can point at; the stored id is minted. Ask for the 3\u20135 that the steering committee watches. On an update, send every milestone the initiative keeps: the file replaces the list.`,
9912
+ de: "[{id?, 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. id? ist ein Label (z. B. \u201Em1\u201C), auf das die milestoneId einer Pendenz zeigen kann; die gespeicherte ID wird gepr\xE4gt. Nach den 3\u20135 fragen, die der Lenkungsausschuss verfolgt. Bei einem Update alle Meilensteine senden, die bleiben sollen: die Datei ersetzt die Liste."
9913
+ }
9914
+ },
9915
+ {
9916
+ key: "risks",
9917
+ hint: {
9918
+ en: '[{id?, title, category, probability, impact, status, residualProbability?, residualImpact?, owner?, mitigation?, raisedDate?, reviewDate?, occurredDate?, note?}] \u2014 the concrete project risks (at most 50, title up to 300 characters): category delivery | vendor | data | people | regulatory | technical | financial; probability and impact 1\u20135 as whole numbers (score = product: low 1\u20134, medium 5\u20139, high 10\u201316, critical 20\u201325); status open | mitigating | closed | occurred (occurred = an issue; give occurredDate, which a closed, resolved issue keeps); the residual pair is the expectation after mitigation (both or neither); owner is free text; mitigation is the plan, its actions are follow-ups linked by riskId; id? is a label (e.g. "r1") for that link, the stored id is minted. Ask for the 2\u20135 risks the steering committee would want named, with owner and mitigation. On an update, send every risk the initiative keeps: the file replaces the list.',
9919
+ de: "[{id?, title, category, probability, impact, status, residualProbability?, residualImpact?, owner?, mitigation?, raisedDate?, reviewDate?, occurredDate?, note?}] \u2014 die konkreten Projektrisiken (h\xF6chstens 50, Titel bis 300 Zeichen): category delivery | vendor | data | people | regulatory | technical | financial; probability und impact 1\u20135 als ganze Zahlen (Score = Produkt: niedrig 1\u20134, mittel 5\u20139, hoch 10\u201316, kritisch 20\u201325); status open | mitigating | closed | occurred (occurred = ein Issue; occurredDate angeben, ein geschlossenes, gel\xF6stes Issue beh\xE4lt es); das Restrisiko-Paar ist die Erwartung nach der Massnahme (beide oder keines); owner ist Freitext; mitigation ist der Plan, seine Schritte sind Pendenzen mit riskId; id? ist ein Label (z. B. \u201Er1\u201C) f\xFCr diese Verkn\xFCpfung, die gespeicherte ID wird gepr\xE4gt. Nach den 2\u20135 Risiken fragen, die der Lenkungsausschuss benannt haben will, mit Owner und Massnahme. Bei einem Update alle Risiken senden, die bleiben sollen: die Datei ersetzt die Liste."
9920
+ }
9921
+ },
9922
+ {
9923
+ key: "followUps",
9924
+ hint: {
9925
+ en: '[{title, dueDate, assigneeName?, assigneeUserId?, doneDate?, milestoneId?, riskId?, note?}] \u2014 agreed next steps: who does what by when (at most 50, title up to 300 characters). assigneeName is a free-text name; assigneeUserId only when the user gives a member id from the app (the app clears an id that is not a member, the name stays). milestoneId / riskId point at a milestone or risk of this same spec by the id you gave it there (e.g. "m1", "r1"); the Composer mints the stored ids and keeps the link. Ask for the open actions, in particular one per severe risk. On an update, send every follow-up the initiative keeps: the file replaces the list.',
9926
+ de: "[{title, dueDate, assigneeName?, assigneeUserId?, doneDate?, milestoneId?, riskId?, note?}] \u2014 vereinbarte n\xE4chste Schritte: wer macht was bis wann (h\xF6chstens 50, Titel bis 300 Zeichen). assigneeName ist ein Freitext-Name; assigneeUserId nur, wenn der Benutzer eine Mitglieds-ID aus der App nennt (die App l\xF6scht eine ID, die kein Mitglied ist, der Name bleibt). milestoneId / riskId zeigen auf einen Meilenstein oder ein Risiko derselben Spezifikation \xFCber die dort vergebene id (z. B. \u201Em1\u201C, \u201Er1\u201C); der Composer pr\xE4gt die gespeicherten IDs und beh\xE4lt die Verkn\xFCpfung. Nach den offenen Schritten fragen, besonders je einem pro schwerem Risiko. Bei einem Update alle Pendenzen senden, die bleiben sollen: die Datei ersetzt die Liste."
9778
9927
  }
9779
9928
  },
9780
9929
  {
@@ -9836,7 +9985,7 @@ function describeZodShape(schema, depth = 0) {
9836
9985
  }
9837
9986
  function buildSchemaDescriptor(sectionShapes) {
9838
9987
  return {
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.",
9988
+ 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, risks, follow-ups and incidents are minted by the Composer \u2014 never invent ids; an id you give a milestone or risk is only a label inside the spec, for a follow-up's milestoneId / riskId. To UPDATE an existing initiative pass its id as `id`; omit it for a new one.",
9840
9989
  requiredFields: REQUIRED_FIELDS,
9841
9990
  enums: {
9842
9991
  status: STATUS_VALUES,
@@ -9868,7 +10017,8 @@ function buildSchemaDescriptor(sectionShapes) {
9868
10017
  },
9869
10018
  optionalSections: OPTIONAL_SECTIONS,
9870
10019
  // Exact shapes of the object/array sections (aiAct, economics, actuals,
9871
- // decisionLog, statusReports, requiredSkills, capabilityImpacts, milestones). Keys ending in "?" are
10020
+ // decisionLog, statusReports, requiredSkills, capabilityImpacts,
10021
+ // milestones, risks, followUps). Keys ending in "?" are
9872
10022
  // optional; "enum[a|b]" lists the allowed values; "<key>" marks a map.
9873
10023
  // Pass these sections as JSON objects/arrays. Any key not listed is
9874
10024
  // rejected with its path.
@@ -9964,7 +10114,7 @@ var parseIfString = (v) => typeof v === "string" ? tryParseJson(v) : v;
9964
10114
  function wireSection(inner, description) {
9965
10115
  return external_exports.preprocess(parseIfString, deepStrict(inner)).describe(description);
9966
10116
  }
9967
- var SECTION_KEYS = ["aiAct", "economics", "actuals", "decisionLog", "statusReports", "requiredSkills", "capabilityImpacts", "milestones"];
10117
+ var SECTION_KEYS = ["aiAct", "economics", "actuals", "decisionLog", "statusReports", "requiredSkills", "capabilityImpacts", "milestones", "risks", "followUps"];
9968
10118
  var SECTION_SCHEMAS = Object.fromEntries(
9969
10119
  SECTION_KEYS.map((k) => [k, contractSection(k)])
9970
10120
  );
@@ -9975,7 +10125,9 @@ var SECTION_DESCRIPTIONS = {
9975
10125
  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.",
9976
10126
  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.",
9977
10127
  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.",
10128
+ 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 \u2014 an id you give (e.g. "m1") is a label a follow-up's milestoneId can point at. An update replaces the list: send all.`,
10129
+ risks: `Risks (max 50, title \u2264300 chars): category delivery|vendor|data|people|regulatory|technical|financial; probability and impact 1\u20135 as whole numbers (score = product); status open|mitigating|closed|occurred (occurred = an issue, with occurredDate); residualProbability + residualImpact = the expectation after mitigation (both or neither); owner (free text), mitigation (the plan), raisedDate, reviewDate, note. Dates dd/mm/yyyy or yyyy-mm-dd; ids minted \u2014 an id you give (e.g. "r1") is a label a follow-up's riskId can point at. An update replaces the list: send all.`,
10130
+ followUps: "Follow-ups (max 50, title \u2264300 chars): who does what by when \u2014 title, dueDate, assigneeName (free text; assigneeUserId only when the user gives a member id from the app), doneDate once done, note; milestoneId / riskId = the id label of a milestone or risk in THIS spec (the Composer keeps the link when it mints the stored ids). Dates dd/mm/yyyy or yyyy-mm-dd; ids minted. An update replaces the list: send all.",
9979
10131
  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."
9980
10132
  };
9981
10133
  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()]));
@@ -10021,6 +10173,8 @@ var compactSpecSchema = external_exports.object({
10021
10173
  requiredSkills: wireSection(SECTION_SCHEMAS.requiredSkills, SECTION_DESCRIPTIONS.requiredSkills).optional(),
10022
10174
  capabilityImpacts: wireSection(SECTION_SCHEMAS.capabilityImpacts, SECTION_DESCRIPTIONS.capabilityImpacts).optional(),
10023
10175
  milestones: wireSection(SECTION_SCHEMAS.milestones, SECTION_DESCRIPTIONS.milestones).optional(),
10176
+ risks: wireSection(SECTION_SCHEMAS.risks, SECTION_DESCRIPTIONS.risks).optional(),
10177
+ followUps: wireSection(SECTION_SCHEMAS.followUps, SECTION_DESCRIPTIONS.followUps).optional(),
10024
10178
  aiRiskTier: external_exports.enum(AI_RISK_TIERS).optional(),
10025
10179
  hitlPosture: external_exports.enum(HITL_POSTURES).optional(),
10026
10180
  dpiaStatus: external_exports.enum(DPIA_STATUSES).optional(),
@@ -10458,15 +10612,74 @@ function assembleInitiative(input, now = /* @__PURE__ */ new Date()) {
10458
10612
  }
10459
10613
  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
10614
  }
10615
+ const risks = spec.risks ?? [];
10616
+ for (const [i, r] of risks.entries()) {
10617
+ if (!r.title.trim()) errors.push(`risks.${i}.title: must not be empty (got only spaces).`);
10618
+ for (const field of ["probability", "impact", "residualProbability", "residualImpact"]) {
10619
+ const v = r[field];
10620
+ if (v !== void 0 && !Number.isInteger(v)) errors.push(`risks.${i}.${field}: must be a whole number 1\u20135 (got ${v}).`);
10621
+ }
10622
+ if (r.residualProbability === void 0 !== (r.residualImpact === void 0)) {
10623
+ errors.push(`risks.${i}: the residual needs both residualProbability and residualImpact \u2014 send the pair, or neither.`);
10624
+ }
10625
+ for (const field of ["raisedDate", "reviewDate", "occurredDate"]) {
10626
+ const v = r[field];
10627
+ if (v !== void 0 && !isCalendarDate(v)) errors.push(`risks.${i}.${field}: "${v}" is not a real calendar date \u2014 dd/mm/yyyy or yyyy-mm-dd`);
10628
+ }
10629
+ if (r.occurredDate !== void 0 && (r.status === "open" || r.status === "mitigating")) {
10630
+ errors.push(`risks.${i}.occurredDate: an open or mitigating risk has not occurred \u2014 set status to occurred (or closed for a resolved issue), or omit the date.`);
10631
+ }
10632
+ if (r.status === "occurred" && r.occurredDate === void 0) {
10633
+ warnings.push(`risks.${i}: status occurred without occurredDate \u2014 the app will show the issue without the date it occurred; send occurredDate (dd/mm/yyyy).`);
10634
+ }
10635
+ if (r.occurredDate && isCalendarDate(r.occurredDate) && r.occurredDate > today) warnings.push(`risks.${i}.occurredDate: ${r.occurredDate} lies in the future \u2014 an issue has already occurred.`);
10636
+ }
10637
+ const followUps = spec.followUps ?? [];
10638
+ const labelCounts = (rows) => {
10639
+ const counts = /* @__PURE__ */ new Map();
10640
+ for (const row of rows) if (row.id !== void 0) counts.set(row.id, (counts.get(row.id) ?? 0) + 1);
10641
+ return counts;
10642
+ };
10643
+ const milestoneLabels = labelCounts(milestones);
10644
+ const riskLabels = labelCounts(risks);
10645
+ const checkLink = (i, field, label, labels, what) => {
10646
+ if (!label) return;
10647
+ const n = labels.get(label) ?? 0;
10648
+ if (n === 0) {
10649
+ errors.push(
10650
+ `followUps.${i}.${field}: "${label}" is not the id of a ${what} in this spec \u2014 give that ${what} an id (any label, e.g. "${field === "milestoneId" ? "m1" : "r1"}") and use it here; the Composer mints the stored ids and keeps the link. The app would clear a link it cannot resolve.`
10651
+ );
10652
+ } else if (n > 1) {
10653
+ errors.push(`followUps.${i}.${field}: "${label}" is the id of ${n} ${what}s in this spec \u2014 ids must be unique for the link to resolve.`);
10654
+ }
10655
+ };
10656
+ for (const [i, f] of followUps.entries()) {
10657
+ if (!f.title.trim()) errors.push(`followUps.${i}.title: must not be empty (got only spaces).`);
10658
+ for (const field of ["dueDate", "doneDate"]) {
10659
+ const v = f[field];
10660
+ if (v !== void 0 && !isCalendarDate(v)) errors.push(`followUps.${i}.${field}: "${v}" is not a real calendar date \u2014 dd/mm/yyyy or yyyy-mm-dd`);
10661
+ }
10662
+ if (f.doneDate && isCalendarDate(f.doneDate) && f.doneDate > today) warnings.push(`followUps.${i}.doneDate: ${f.doneDate} lies in the future \u2014 a done date marks a follow-up already done.`);
10663
+ checkLink(i, "milestoneId", f.milestoneId, milestoneLabels, "milestone");
10664
+ checkLink(i, "riskId", f.riskId, riskLabels, "risk");
10665
+ if (f.assigneeUserId !== void 0 && !f.assigneeName?.trim()) {
10666
+ warnings.push(`followUps.${i}.assigneeUserId: the Composer cannot verify workspace members, and the app clears an id that is not a member of the workspace \u2014 send assigneeName too, so the follow-up keeps its assignee either way.`);
10667
+ }
10668
+ }
10461
10669
  const norm2 = (v) => (v ?? "").trim().toLowerCase();
10462
10670
  const others = context?.initiatives ?? [];
10463
10671
  const ext = norm2(spec.externalId);
10464
10672
  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
10673
  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.");
10674
+ for (const [key, what] of [
10675
+ ["milestones", "milestones"],
10676
+ ["risks", "risks"],
10677
+ ["followUps", "follow-ups"]
10678
+ ]) {
10679
+ if (spec[key] === void 0) {
10680
+ warnings.push(`${key}: none sent, and the app will offer this file as an update \u2014 it replaces the initiative's ${what}, so any the app holds are removed. Send the full list to keep them.`);
10681
+ }
10682
+ }
10470
10683
  }
10471
10684
  let businessUnit = spec.businessUnit;
10472
10685
  let aiCategory = spec.aiCategory;
@@ -10506,6 +10719,24 @@ function assembleInitiative(input, now = /* @__PURE__ */ new Date()) {
10506
10719
  }
10507
10720
  const stamp = now.toISOString();
10508
10721
  const aiAct = spec.aiAct;
10722
+ const trimTitles = (rows) => rows?.map((r) => ({ ...r, title: r.title.trim() }));
10723
+ const mintedMilestones = trimTitles(mintNestedIds(spec.milestones, stamp));
10724
+ const mintedRisks = trimTitles(mintNestedIds(spec.risks, stamp));
10725
+ const mintedIdByLabel = (given, minted) => new Map(
10726
+ (given ?? []).flatMap((row, i) => {
10727
+ const minted_ = minted?.[i]?.id;
10728
+ return row.id !== void 0 && minted_ !== void 0 ? [[row.id, minted_]] : [];
10729
+ })
10730
+ );
10731
+ const milestoneIds = mintedIdByLabel(milestones, mintedMilestones);
10732
+ const riskIds = mintedIdByLabel(risks, mintedRisks);
10733
+ const mintedFollowUps = trimTitles(mintNestedIds(spec.followUps, stamp))?.map(
10734
+ ({ milestoneId, riskId, ...f }) => ({
10735
+ ...f,
10736
+ ...milestoneId ? { milestoneId: milestoneIds.get(milestoneId) ?? milestoneId } : {},
10737
+ ...riskId ? { riskId: riskIds.get(riskId) ?? riskId } : {}
10738
+ })
10739
+ );
10509
10740
  const candidate = {
10510
10741
  ...spec,
10511
10742
  id: spec.id ?? randomUUID(),
@@ -10518,7 +10749,9 @@ function assembleInitiative(input, now = /* @__PURE__ */ new Date()) {
10518
10749
  evaluation,
10519
10750
  decisionLog: mintNestedIds(spec.decisionLog, stamp),
10520
10751
  statusReports: mintNestedIds(spec.statusReports, stamp),
10521
- milestones: mintNestedIds(spec.milestones, stamp)?.map((m) => ({ ...m, title: m.title.trim() })),
10752
+ milestones: mintedMilestones,
10753
+ risks: mintedRisks,
10754
+ followUps: mintedFollowUps,
10522
10755
  aiAct: aiAct ? { ...aiAct, ...aiAct.incidents ? { incidents: mintNestedIds(aiAct.incidents, stamp, true) } : {} } : void 0,
10523
10756
  createdAt: stamp,
10524
10757
  updatedAt: stamp
@@ -10556,7 +10789,7 @@ var IMPORT_INSTRUCTIONS = [
10556
10789
  "2. In the BICon app (signed in to the target organisation), open Import/Export.",
10557
10790
  "3. If the initiative carries EU-AI-Act data, make sure the organisation's EU-AI-Act module is switched on (Settings \u203A AI Act) \u2014 the app strips AI-Act fields while it is off.",
10558
10791
  "4. In the 'Single initiative' card, drop the file (or Browse).",
10559
- "5. Review the preview \u2014 it should show 0 warnings \u2014 then choose 'Add as new' (or 'Update' when the file carries an existing initiative's id, Initiative ID or name \u2014 the app keeps that initiative's id and creation date, and REPLACES everything else with this file, decision log and status reports included) and Confirm.",
10792
+ "5. Review the preview \u2014 it should show 0 warnings \u2014 then choose 'Add as new' (or 'Update' when the file carries an existing initiative's id, Initiative ID or name \u2014 the app keeps that initiative's id and creation date, and REPLACES everything else with this file, decision log, status reports, milestones, risks and follow-ups included) and Confirm.",
10560
10793
  "6. The initiative appears in the Inventory with the derived dimension scores."
10561
10794
  ].join("\n");
10562
10795
 
@@ -10588,7 +10821,7 @@ function createServer() {
10588
10821
  async () => text({
10589
10822
  capabilities: [
10590
10823
  "strict typed schemas: unknown keys anywhere in the spec are rejected with their exact path (never silently dropped)",
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",
10824
+ "sections (aiAct/economics/actuals/decisionLog/statusReports/requiredSkills/capabilityImpacts/milestones/risks/followUps) accept a JSON object/array or the same JSON as a string; row ids are minted by the Composer, and a follow-up's milestoneId / riskId names a milestone or risk of the same spec by the id label given there",
10592
10825
  "dates accepted as dd/mm/yyyy, dd.mm.yyyy or yyyy-mm-dd (stored as yyyy-mm-dd)",
10593
10826
  "get_initiative_schema: sectionShapes, aiActVocabularies, portfolio-mode wording overlays",
10594
10827
  "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.6.0",
3
+ "version": "0.8.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",