docs(fleet): tier the north star and declare the tier-0 operator surface (#1337)
ci/woodpecker/push/publish Pipeline was canceled
ci/woodpecker/push/publish Pipeline was canceled
This commit was merged in pull request #1337.
This commit is contained in:
@@ -147,11 +147,11 @@ describe('renderNorthStarMarkdown', () => {
|
||||
'standing_objectives:',
|
||||
' - { id: NS-1, text: t }',
|
||||
'success_criteria:',
|
||||
' - { id: AC-NS-1, text: t }',
|
||||
' - { id: AC-NS-1, text: t, tier: 0 }',
|
||||
'workstreams:',
|
||||
' - { id: A, title: t }',
|
||||
'goals:',
|
||||
' - { id: A1, title: t, phase: 1, priority: must-have, depends_on: [] }',
|
||||
' - { id: A1, title: t, phase: 1, tier: 0, priority: must-have, depends_on: [] }',
|
||||
'assumptions:',
|
||||
' - { id: ASM-1, vetoable: true, text: t }',
|
||||
'spend:',
|
||||
|
||||
@@ -191,6 +191,10 @@ export interface NorthStarIdText {
|
||||
text: string;
|
||||
}
|
||||
|
||||
export interface NorthStarCriterion extends NorthStarIdText {
|
||||
tier: number;
|
||||
}
|
||||
|
||||
export interface NorthStarWorkstream {
|
||||
id: string;
|
||||
title: string;
|
||||
@@ -200,6 +204,8 @@ export interface NorthStarGoal {
|
||||
id: string;
|
||||
title: string;
|
||||
phase: number;
|
||||
/** Capability tier this goal serves: 0 dogfood, 1 MVP, 2 full vision. Orthogonal to phase, which is build order. */
|
||||
tier: number;
|
||||
priority: string;
|
||||
depends_on: string[];
|
||||
}
|
||||
@@ -220,7 +226,7 @@ export interface NorthStar {
|
||||
mission: string;
|
||||
substrate: { note: string };
|
||||
standing_objectives: NorthStarIdText[];
|
||||
success_criteria: NorthStarIdText[];
|
||||
success_criteria: NorthStarCriterion[];
|
||||
workstreams: NorthStarWorkstream[];
|
||||
goals: NorthStarGoal[];
|
||||
assumptions: NorthStarAssumption[];
|
||||
@@ -280,9 +286,13 @@ export function parseNorthStar(rawText: string): NorthStar {
|
||||
standing_objectives: requireArray(parsed.standing_objectives, 'standing_objectives').map(
|
||||
(row, i) => idText(row, 'standing_objectives', i),
|
||||
),
|
||||
success_criteria: requireArray(parsed.success_criteria, 'success_criteria').map((row, i) =>
|
||||
idText(row, 'success_criteria', i),
|
||||
),
|
||||
success_criteria: requireArray(parsed.success_criteria, 'success_criteria').map((row, i) => {
|
||||
const tier = (row as Record<string, unknown>)?.tier;
|
||||
if (typeof tier !== 'number') {
|
||||
throw new Error(`NORTH_STAR.yaml: success_criteria[${i}].tier must be a number.`);
|
||||
}
|
||||
return { ...idText(row, 'success_criteria', i), tier };
|
||||
}),
|
||||
workstreams: requireArray(parsed.workstreams, 'workstreams').map((row, i) => {
|
||||
const ws = row as Record<string, unknown>;
|
||||
return {
|
||||
@@ -300,10 +310,15 @@ export function parseNorthStar(rawText: string): NorthStar {
|
||||
if (typeof phase !== 'number') {
|
||||
throw new Error(`NORTH_STAR.yaml: goals[${i}].phase must be a number.`);
|
||||
}
|
||||
const tier = goal?.tier;
|
||||
if (typeof tier !== 'number') {
|
||||
throw new Error(`NORTH_STAR.yaml: goals[${i}].tier must be a number.`);
|
||||
}
|
||||
return {
|
||||
id: requireString(goal?.id, `goals[${i}].id`),
|
||||
title: requireString(goal?.title, `goals[${i}].title`),
|
||||
phase,
|
||||
tier,
|
||||
priority: requireString(goal?.priority, `goals[${i}].priority`),
|
||||
depends_on: dependsRaw.map((dep, j) => requireString(dep, `goals[${i}].depends_on[${j}]`)),
|
||||
};
|
||||
@@ -349,7 +364,7 @@ function renderMarkdownTable(headers: string[], rows: string[][]): string[] {
|
||||
* Pure function of its input — same input always yields byte-identical output,
|
||||
* so the round-trip (YAML → render → write) is stable across runs. No clock, no
|
||||
* network, no CLI. Layout follows the repo's existing doctrine-doc convention
|
||||
* (heading, blockquote banner, then sections + tables, e.g. north-star.md /
|
||||
* (heading, blockquote banner, then sections + tables, e.g. FLEET-DOCTRINE.md /
|
||||
* mission-control/BOARD.md).
|
||||
*/
|
||||
export function renderNorthStarMarkdown(ns: NorthStar): string {
|
||||
@@ -362,7 +377,7 @@ export function renderNorthStarMarkdown(ns: NorthStar): string {
|
||||
'> Projected deterministically from [`NORTH_STAR.yaml`](./NORTH_STAR.yaml) by the pure',
|
||||
);
|
||||
lines.push('> generator in `packages/mosaic/src/commands/fleet.ts` (`renderNorthStarMarkdown`).');
|
||||
lines.push('> Edit the YAML, then regenerate. Self-contained Mosaic — no Hermes dependency.');
|
||||
lines.push('> Edit the YAML, then regenerate. Self-contained Mosaic.');
|
||||
lines.push('');
|
||||
|
||||
lines.push('## Mission');
|
||||
@@ -385,7 +400,7 @@ export function renderNorthStarMarkdown(ns: NorthStar): string {
|
||||
lines.push('## Success criteria');
|
||||
lines.push('');
|
||||
for (const ac of ns.success_criteria) {
|
||||
lines.push(`- **${ac.id}** — ${ac.text}`);
|
||||
lines.push(`- **${ac.id}** (tier ${ac.tier}) — ${ac.text}`);
|
||||
}
|
||||
lines.push('');
|
||||
|
||||
@@ -403,10 +418,11 @@ export function renderNorthStarMarkdown(ns: NorthStar): string {
|
||||
lines.push('');
|
||||
lines.push(
|
||||
...renderMarkdownTable(
|
||||
['id', 'title', 'phase', 'priority', 'depends_on'],
|
||||
['id', 'title', 'tier', 'phase', 'priority', 'depends_on'],
|
||||
ns.goals.map((goal) => [
|
||||
goal.id,
|
||||
goal.title,
|
||||
String(goal.tier),
|
||||
String(goal.phase),
|
||||
goal.priority,
|
||||
goal.depends_on.length > 0 ? goal.depends_on.join(', ') : '—',
|
||||
|
||||
@@ -922,8 +922,8 @@ describe('fleet operator documentation', (): void => {
|
||||
);
|
||||
expect(
|
||||
surfaces.filter((surface): boolean => surface.category === 'InlineLiteral'),
|
||||
).toHaveLength(863);
|
||||
expect(surfaces).toHaveLength(887);
|
||||
).toHaveLength(882);
|
||||
expect(surfaces).toHaveLength(906);
|
||||
|
||||
const rosterSource = await readFile(join(fleetDocs, 'examples', 'roster-v2.yaml'), 'utf8');
|
||||
const auxiliary: CodeSurface = {
|
||||
|
||||
Reference in New Issue
Block a user