Skip to content

Commit 12bd153

Browse files
committed
Add weighted station stakeholder mappings
1 parent 2fb682a commit 12bd153

20 files changed

Lines changed: 1562 additions & 99 deletions

README.md

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,21 @@ import {
5353

5454
The `method-engine` export is intended for reusable APIOps workflow logic. It gives CLIs, AI agents, apps, and APIs the same station recommendation, resource lookup, and canvas generation behavior without reimplementing the method rules.
5555

56-
Sticky note authoring should uses the shared palette exposed by the method engine:
56+
The method now also includes reusable stakeholder data:
57+
58+
- `src/data/method/stakeholders.json` defines the shared stakeholder catalog
59+
- `src/data/method/station-stakeholders.json` maps each station to weighted stakeholder participation
60+
- `src/data/method/<locale>/labels.stakeholders.json` stores localized stakeholder titles, descriptions, and involvement labels
61+
62+
Stakeholder involvement uses three lightweight levels:
63+
64+
- `lead`
65+
- `core`
66+
- `consulted`
67+
68+
This is meant to keep APIOps Cycles explicitly cross-functional, including business, security, compliance, support, and consumer voices in architecture and design work where relevant.
69+
70+
Sticky note authoring should use the shared palette exposed by the method engine:
5771

5872
- `benefit`: `#C0EB6A`
5973
- `neutral`: `#DFDDC5`
@@ -88,16 +102,17 @@ If you spot a problem in the documentation or have an idea for new content, plea
88102

89103
### Editing or adding content
90104

91-
The main method content files (instructions, guidelines, method structure) are located in the the JSON files at `src/data/method/`. These base files (`lines.json`, `stations.json`, `resources.json`, `criteria.json` and `station-criteria.json`) are not localized and live at the root of the folder. Textual values in them reference label keys. English labels are in `src/data/method/en-US` and translations are provided in `labels.lines.json`, `labels.stations.json`, `labels.resources.json` and `labels.criteria.json` under each locale folder. Some longer or more complex resource pages like the API Audit Checklist also use markdown snippets `src/snippets/` linked to the `resources.json`. Do not use any frontmatter in the snippet files. Any supported markdown markup is ok. See references from [Starlight markdown reference](https://starlight.astro.build/guides/authoring-content/) and [Extended markdown reference](https://www.markdownguide.org/extended-syntax/).
105+
The main method content files (instructions, guidelines, method structure) are located in the JSON files at `src/data/method/`. These base files (`lines.json`, `stations.json`, `resources.json`, `criteria.json`, `station-criteria.json`, `stakeholders.json`, and `station-stakeholders.json`) are not localized and live at the root of the folder. Textual values in them reference label keys. English labels are in `src/data/method/en` and translations are provided in `labels.lines.json`, `labels.stations.json`, `labels.resources.json`, `labels.criteria.json`, and `labels.stakeholders.json` under each locale folder. Some longer or more complex resource pages like the API Audit Checklist also use markdown snippets `src/snippets/` linked to the `resources.json`. Do not use any frontmatter in the snippet files. Any supported markdown markup is ok. See references from [Starlight markdown reference](https://starlight.astro.build/guides/authoring-content/) and [Extended markdown reference](https://www.markdownguide.org/extended-syntax/).
92106

93-
Each station links to specific entry criteria followed by the next core station's criteria as exit criteria.`criteria.json`, `station-criteria.json` and `labels.criteria.json`
107+
Each station links to specific entry criteria followed by the next core station's criteria as exit criteria. Stakeholder participation is modeled separately through `stakeholders.json`, `station-stakeholders.json`, and `labels.stakeholders.json`.
94108

95109
#### Editing existing content of Method pages (metrolines, core- and substations, resources).
96110
1. Go to `src/data/method/en` and edit the content in English (English is considered the master langauge, and for the translations to work for other languages, it must always be the first to be edited).
97111
2. Validate that your changes work by running the schema validations (`npm test`)
98112
3. Follow the translation guide if you are able to translate the content to other languages manually or automatically.
99-
4. Commit your code and make a pull request.
100-
5. If you were not able to create the translations of your changes to all languages, create an issue for in the repository for the translations.
113+
4. Update all supported locales before considering the change complete. This includes criteria wording and stakeholder labels when those are touched.
114+
5. Commit your code and make a pull request.
115+
6. If you were not able to create the translations of your changes to all languages, create an issue in the repository for the translations.
101116

102117
#### Translating the language manually or with automated services (new or existing languages with new or changed content)
103118

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,12 @@
2323
"./localizedData.json": "./src/data/canvas/localizedData.json",
2424
"./method/stations.json": "./src/data/method/stations.json",
2525
"./method/resources.json": "./src/data/method/resources.json",
26-
"./method/station-criteria.json": "./src/data/method/station-criteria.json"
26+
"./method/station-criteria.json": "./src/data/method/station-criteria.json",
27+
"./method/stakeholders.json": "./src/data/method/stakeholders.json",
28+
"./method/station-stakeholders.json": "./src/data/method/station-stakeholders.json"
2729
},
2830
"scripts": {
29-
"test": "node scripts/validate.mjs && node scripts/test-note-colors.mjs && node scripts/test-print-method-snippet.mjs",
31+
"test": "node scripts/validate.mjs && node scripts/test-method-stakeholders.mjs && node scripts/test-note-colors.mjs && node scripts/test-print-method-snippet.mjs",
3032
"release:create-apiops:pack": "npm pack --workspace packages/create-apiops",
3133
"release:create-apiops:publish": "npm publish --workspace packages/create-apiops --access public",
3234
"check:packaging:skills": "node scripts/check-packaging-skills.mjs",
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import assert from "node:assert/strict";
2+
import * as methodEngine from "../src/lib/method-engine.js";
3+
4+
const stations = methodEngine.getStations();
5+
const stationIds = new Set(stations.map((station) => station.id));
6+
const stakeholderIds = new Set(methodEngine.getStakeholders().map((stakeholder) => stakeholder.id));
7+
const stationStakeholderMap = methodEngine.getStationStakeholderMap();
8+
9+
for (const station of stations) {
10+
const entries = stationStakeholderMap[station.id];
11+
assert.ok(entries, `Missing stakeholder mapping for ${station.id}.`);
12+
assert.ok(entries.length > 0, `Expected at least one stakeholder mapping for ${station.id}.`);
13+
14+
const seenStakeholders = new Set();
15+
const leads = entries.filter((entry) => entry.involvement === "lead");
16+
const cores = entries.filter((entry) => entry.involvement === "core");
17+
18+
assert.equal(leads.length, 1, `Expected exactly one lead for ${station.id}.`);
19+
assert.ok(cores.length > 0, `Expected at least one core stakeholder for ${station.id}.`);
20+
21+
for (const entry of entries) {
22+
assert.ok(stakeholderIds.has(entry.stakeholder), `Unknown stakeholder ${entry.stakeholder} in ${station.id}.`);
23+
assert.ok(!seenStakeholders.has(entry.stakeholder), `Duplicate stakeholder ${entry.stakeholder} in ${station.id}.`);
24+
seenStakeholders.add(entry.stakeholder);
25+
}
26+
27+
const localizedStakeholders = methodEngine.buildStationStakeholderData(station.id, "fi");
28+
assert.equal(localizedStakeholders.length, entries.length, `Localized stakeholder count mismatch for ${station.id}.`);
29+
assert.ok(localizedStakeholders.every((entry) => entry.title && entry.description && entry.involvementLabel), `Incomplete localized stakeholder data for ${station.id}.`);
30+
}
31+
32+
for (const stationId of Object.keys(stationStakeholderMap)) {
33+
assert.ok(stationIds.has(stationId), `Stakeholder mapping references unknown station ${stationId}.`);
34+
}
35+
36+
const startData = methodEngine.buildStartData("en");
37+
assert.ok(startData.every((station) => Array.isArray(station.stakeholders) && station.stakeholders.length > 0), "Expected stakeholders in start data.");
38+
39+
const designData = methodEngine.buildStationResourceData("api-design", "en");
40+
assert.ok(Array.isArray(designData.stakeholders) && designData.stakeholders.length > 0, "Expected stakeholders in station resource data.");
41+
assert.ok(designData.stakeholders.some((entry) => entry.id === "security-specialist"), "Expected api-design to include security-specialist.");
42+
assert.ok(designData.stakeholders.some((entry) => entry.id === "compliance-legal-specialist"), "Expected api-design to include compliance-legal-specialist.");
43+
assert.ok(designData.stakeholders.some((entry) => entry.id === "business-owner"), "Expected api-design to include business-owner.");
44+
45+
const architectureData = methodEngine.buildStationResourceData("api-platform-architecture", "en");
46+
assert.ok(architectureData.stakeholders.some((entry) => entry.id === "security-specialist"), "Expected api-platform-architecture to include security-specialist.");
47+
assert.ok(architectureData.stakeholders.some((entry) => entry.id === "compliance-legal-specialist"), "Expected api-platform-architecture to include compliance-legal-specialist.");
48+
49+
const fallbackStakeholders = methodEngine.buildStationStakeholderData("api-product-strategy", "sv");
50+
assert.ok(fallbackStakeholders.some((entry) => entry.involvementLabel === "Lead"), "Expected missing locale fallback to English stakeholder labels.");
51+
52+
console.log("Method stakeholder regression test passed.");

scripts/validate.mjs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@ async function gatherTemplateFiles() {
5151
await validate('src/schemas/criteria.schema.json', ['src/data/method/criteria.json']);
5252
await validate('src/schemas/lines.schema.json', ['src/data/method/lines.json']);
5353
await validate('src/schemas/resources.schema.json', ['src/data/method/resources.json']);
54+
await validate('src/schemas/stakeholders.schema.json', ['src/data/method/stakeholders.json']);
5455
await validate('src/schemas/station-criteria.schema.json', ['src/data/method/station-criteria.json']);
56+
await validate('src/schemas/station-stakeholders.schema.json', ['src/data/method/station-stakeholders.json']);
5557
await validate('src/schemas/stations.schema.json', ['src/data/method/stations.json']);
5658
await validate('src/schemas/canvasData.schema.json', ['src/data/canvas/canvasData.json']);
5759
await validate('src/schemas/canvas-localized.schema.json', ['src/data/canvas/localizedData.json']);

src/data/method/criteria.json

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[
22
{
33
"id": "metrics-feedback-available",
4-
"description": "Insights from metrics and feedback are available to optimize existing APIs."
4+
"description": "Relevant market signals, feedback, or operational insights are available to guide this API opportunity."
55
},
66
{
77
"id": "business-goals-defined",
@@ -13,7 +13,7 @@
1313
},
1414
{
1515
"id": "stakeholder-approval",
16-
"description": "Stakeholders approve strategy discussions."
16+
"description": "Relevant stakeholders agree this API opportunity is worth exploring and prioritizing."
1717
},
1818
{
1919
"id": "api-opportunity-documented",
@@ -25,11 +25,11 @@
2525
},
2626
{
2727
"id": "hide-backend-discrepancies",
28-
"description": "The goal of the API is to hide backend data models and discrepancies."
28+
"description": "The API is intended to shield consumers from backend complexity and inconsistencies."
2929
},
3030
{
3131
"id": "value-prop-validated",
32-
"description": "The value proposition validates with key stakeholders."
32+
"description": "The API value proposition has been reviewed and validated with the relevant business and consumer stakeholders."
3333
},
3434
{
3535
"id": "consumer-segments-identified",
@@ -41,46 +41,46 @@
4141
},
4242
{
4343
"id": "architecture-patterns-validated",
44-
"description": "The API architecture uses patterns that promote reusability and integration, and is validated with stakeholders."
44+
"description": "The chosen API architecture and platform patterns have been validated with the relevant architecture, security, and platform stakeholders."
4545
},
4646
{
4747
"id": "design-reflects-business-value",
48-
"description": "The API's design and endpoints have a clear connection to their business value and features."
48+
"description": "The API design and exposed capabilities clearly trace back to business value and user needs."
4949
},
5050
{
5151
"id": "api-consistency",
52-
"description": "API has a consistent design with our other API products."
52+
"description": "The API design follows our shared API product and design conventions."
5353
},
5454
{
5555
"id": "api-contract-tested",
5656
"description": "The API contract is tested and meets functional and non-functional requirements."
5757
},
5858
{
5959
"id": "api-description-available",
60-
"description": "The API and its endpoints have descriptions that explain their business value and features."
60+
"description": "The API and its exposed capabilities are described clearly enough for review, audit, and onboarding."
6161
},
6262
{
6363
"id": "audit-passed",
6464
"description": "The API passes compliance, security, and audit checks."
6565
},
6666
{
6767
"id": "audit-reports-shared",
68-
"description": "Audit reports are shared with stakeholders."
68+
"description": "Audit findings and remediation decisions are shared with the relevant stakeholders."
6969
},
7070
{
7171
"id": "api-ready-for-publishing",
72-
"description": "The API is ready to be published to the appropriate gateways and environments to support reusability for multiple API consumers."
72+
"description": "The API is ready to be deployed and exposed through the intended gateways and environments."
7373
},
7474
{
7575
"id": "api-documentation-ready",
76-
"description": "API documentation is complete and ready for publishing."
76+
"description": "Consumer-facing API documentation is complete enough for publishing and onboarding."
7777
},
7878
{
7979
"id": "consumer-support-ready",
80-
"description": "API registration, support, and communication processes are in place."
80+
"description": "Registration, support, and communication processes are ready for API consumers."
8181
},
8282
{
8383
"id": "legal-compliance-clear",
84-
"description": "Legal and compliance requirements are precise enough for publishing."
84+
"description": "Legal, privacy, and compliance requirements for publishing are defined and understood."
8585
}
86-
]
86+
]
Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
11
{
22
"exit_criteria": "Austrittskriterien",
33
"entry_criteria": "Eintrittskriterien",
4-
"criterion.metrics-feedback-available": "Erkenntnisse aus Metriken und Feedback stehen zur Optimierung bestehender APIs zur Verfügung",
4+
"criterion.metrics-feedback-available": "Relevante Marktsignale, Feedback oder operative Erkenntnisse sind verfügbar, um diese API-Möglichkeit zu steuern.",
55
"criterion.business-goals-defined": "Geschäftsziele sind definiert",
66
"criterion.market-research-done": "Marktforschung identifiziert API-Möglichkeiten",
7-
"criterion.stakeholder-approval": "Stakeholder genehmigen Strategiediskussionen",
7+
"criterion.stakeholder-approval": "Relevante Stakeholder stimmen zu, dass diese API-Möglichkeit es wert ist, sie zu erkunden und Priorität einzuräumen.",
88
"criterion.api-opportunity-documented": "Individuelle API-Möglichkeiten werden identifiziert und dokumentiert",
99
"criterion.api-reusability": "Die API erfüllt einen klaren Geschäftsbedarf und ist für mehrere API-Nutzer wiederverwendbar",
10-
"criterion.hide-backend-discrepancies": "Das Ziel der API ist es, Backend-Datenmodelle und Diskrepanzen zu verbergen.",
11-
"criterion.value-prop-validated": "Das Wertversprechen wird mit den wichtigsten Stakeholdern validiert.",
10+
"criterion.hide-backend-discrepancies": "Die API ist dazu gedacht, Verbraucher vor Backend-Komplexität und Inkonsistenzen zu schützen.",
11+
"criterion.value-prop-validated": "Die API-Wert proposition wurde mit den relevanten Geschäft und Verbraucher-Stakeholdern überprüft und validiert.",
1212
"criterion.consumer-segments-identified": "API-Nutzersegmente (intern und extern) werden identifiziert.",
1313
"criterion.api-roadmap-defined": "Hochrangige Roadmaps für die API-Entwicklung werden erstellt.",
14-
"criterion.architecture-patterns-validated": "Die API-Architektur verwendet Muster, die die Wiederverwendbarkeit und Integration fördern, und wird mit den Stakeholdern validiert.",
15-
"criterion.design-reflects-business-value": "Das Design und die Endpunkte der API stehen in klarem Zusammenhang mit ihrem geschäftlichen Nutzen und ihren Funktionen.",
16-
"criterion.api-consistency": "Die API weist ein einheitliches Design mit unseren anderen API-Produkten auf.",
14+
"criterion.architecture-patterns-validated": "Die gewählten API-Architektur- und Plattformmuster wurden mit den relevanten Architektur-, Sicherheits- und Plattform-Stakeholdern validiert.",
15+
"criterion.design-reflects-business-value": "Die API-Design und die offengelegten Funktionen spiegeln klar den Geschäftswert und die Bedürfnisse der Benutzer wider.",
16+
"criterion.api-consistency": "Das API-Design folgt unseren gemeinsamen API-Produkt- und Design-Vorgaben.",
1717
"criterion.api-contract-tested": "Der API-Vertrag wurde getestet und erfüllt die funktionalen und nicht-funktionalen Anforderungen.",
18-
"criterion.api-description-available": "Die API und ihre Endpunkte verfügen über Beschreibungen, die ihren geschäftlichen Nutzen und ihre Funktionen erläutern.",
18+
"criterion.api-description-available": "Die API und ihre offengelegten Funktionen sind ausreichend beschrieben für Überprüfung, Auditierung und Onboarding.",
1919
"criterion.audit-passed": "Die API besteht Compliance-, Sicherheits- und Audit-Prüfungen.",
20-
"criterion.audit-reports-shared": "Auditberichte werden mit den Stakeholdern geteilt.",
21-
"criterion.api-ready-for-publishing": "Die API kann in den entsprechenden Gateways und Umgebungen veröffentlicht werden, um die Wiederverwendbarkeit für mehrere API-Nutzer zu unterstützen.",
22-
"criterion.api-documentation-ready": "Die API-Dokumentation ist vollständig und bereit zur Veröffentlichung.",
23-
"criterion.consumer-support-ready": "Prozesse für die API-Registrierung, den Support und die Kommunikation sind eingerichtet.",
24-
"criterion.legal-compliance-clear": "Die rechtlichen und Compliance-Anforderungen sind für die Veröffentlichung präzise genug."
20+
"criterion.audit-reports-shared": "API-Auditberichte wurden mit relevanten Stakeholdern geteilt.",
21+
"criterion.api-ready-for-publishing": "Die API ist bereit, für Verbraucher verfügbar gemacht zu werden.",
22+
"criterion.api-documentation-ready": "Die API-Dokumentation ist vollständig und für die Veröffentlichung und das Onboarding geeignet.",
23+
"criterion.consumer-support-ready": "Registrierungs-, Support- und Kommunikationsprozesse sind für API-Nutzer bereit.",
24+
"criterion.legal-compliance-clear": "Rechtliche, datenschutzrechtliche und Compliance-Anforderungen für die Veröffentlichung sind definiert und verstanden."
2525
}

0 commit comments

Comments
 (0)