konpeki 0.3.1 → 0.4.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.
- package/AGENTS.md +21 -28
- package/AUTHORING.md +68 -229
- package/CONTRIBUTING.md +10 -23
- package/README.md +98 -106
- package/SETUP.md +49 -129
- package/docs/development.md +43 -256
- package/docs/workflow.md +6 -108
- package/html/README.md +140 -0
- package/html/browser.ts +103 -0
- package/html/document.ts +38 -0
- package/html/floor.ts +34 -0
- package/html/index.html +5 -0
- package/html/inspect.ts +313 -0
- package/html/preview.css +62 -0
- package/html/preview.tsx +463 -0
- package/html/review-hints.ts +63 -0
- package/html/server.ts +99 -0
- package/html/source.ts +104 -0
- package/html/starter.ts +6 -0
- package/html/theme-authoring.md +176 -0
- package/html/theme.md +61 -0
- package/index.html +9 -9
- package/package.json +21 -37
- package/plugin.json +1 -1
- package/public/og.png +0 -0
- package/runtime/browser-B-29TH1a.mjs +595 -0
- package/runtime/floor-Cmk7G3pU.mjs +41 -0
- package/runtime/konpeki.mjs +90 -1410
- package/runtime/server-BAqC_5WD.mjs +2 -0
- package/runtime/server-DfRpfcY9.mjs +205 -0
- package/runtime/source-B_Ui9tMp.mjs +141 -0
- package/runtime/source-CZQq9GUO.mjs +2 -0
- package/skills/konpeki/SKILL.md +88 -172
- package/skills/konpeki/assets/blank.html +17 -0
- package/skills/konpeki/floor.md +76 -0
- package/skills/konpeki/references/cover.md +27 -0
- package/skills/konpeki/references/long-document.md +40 -0
- package/skills/konpeki/references/one-pager.md +27 -0
- package/skills/konpeki/references/patterns.md +118 -0
- package/skills/konpeki/references/resume.md +28 -0
- package/skills/konpeki/references/slides.md +28 -0
- package/skills/konpeki/scripts/ensure-runtime.mjs +10 -31
- package/skills/konpeki/scripts/prepare-document.mjs +25 -14
- package/src/components/PageBoard.tsx +156 -0
- package/src/lib/alignment.ts +21 -0
- package/src/lib/page-board.ts +25 -0
- package/src/lib/review-position.ts +19 -0
- package/src/styles/base.css +1 -10
- package/src/styles/feedback.css +2 -1
- package/src/styles/shell.css +94 -354
- package/theme-base.css +90 -0
- package/theme.css +56 -0
- package/vite.config.ts +2 -5
- package/composition/README.md +0 -156
- package/composition/compile.ts +0 -227
- package/composition/document.ts +0 -600
- package/composition/schema.json +0 -3001
- package/composition/schema.ts +0 -437
- package/composition/theme-tokens.ts +0 -16
- package/composition/types.ts +0 -269
- package/composition/validate.ts +0 -226
- package/composition/vector.ts +0 -143
- package/composition/visualizations.ts +0 -319
- package/design/README.md +0 -17
- package/design/palettes/README.md +0 -14
- package/design/palettes/base.ts +0 -14
- package/design/palettes/candidates.ts +0 -19
- package/design/palettes/index.ts +0 -78
- package/design/review/color-theme.md +0 -44
- package/design/review/layout.md +0 -16
- package/design/review/text.md +0 -18
- package/design/review/typography.md +0 -15
- package/design/review/visuals.md +0 -31
- package/design/semantic-patterns.md +0 -43
- package/design/themes/README.md +0 -40
- package/design/themes/index.ts +0 -24
- package/design/visual-languages/technical-product.md +0 -17
- package/design/visual-review.md +0 -88
- package/lib/assets.d.ts +0 -8
- package/lib/charts.ts +0 -18
- package/lib/contrast.ts +0 -16
- package/lib/layouts.ts +0 -50
- package/lib/slide.tsx +0 -42
- package/lib/taste.ts +0 -17
- package/lib/text.tsx +0 -89
- package/lib/typeface.ts +0 -44
- package/scripts/migrate-react-page.ts +0 -120
- package/skills/konpeki/assets/blank.json +0 -23
- package/slides/README.md +0 -56
- package/slides/architecture/PROMPT.md +0 -31
- package/slides/architecture/index.tsx +0 -102
- package/slides/article-brief/PROMPT.md +0 -35
- package/slides/article-brief/index.tsx +0 -71
- package/slides/bar-chart/PROMPT.md +0 -39
- package/slides/bar-chart/index.tsx +0 -97
- package/slides/comparison/PROMPT.md +0 -29
- package/slides/comparison/index.tsx +0 -95
- package/slides/decision-memo/PROMPT.md +0 -34
- package/slides/decision-memo/index.tsx +0 -85
- package/slides/delivery-plan/PROMPT.md +0 -45
- package/slides/delivery-plan/index.tsx +0 -105
- package/slides/drawing-references.md +0 -32
- package/slides/experiment/PROMPT.md +0 -44
- package/slides/experiment/index.tsx +0 -127
- package/slides/github-cover/PROMPT.md +0 -21
- package/slides/github-cover/README.md +0 -21
- package/slides/github-cover/author.ts +0 -67
- package/slides/github-cover/composition.json +0 -595
- package/slides/incident-workflow/PROMPT.md +0 -57
- package/slides/incident-workflow/index.tsx +0 -78
- package/slides/introducing-konpeki/PROMPT.md +0 -30
- package/slides/introducing-konpeki/README.md +0 -44
- package/slides/introducing-konpeki/SOURCE.md +0 -19
- package/slides/introducing-konpeki/author.ts +0 -165
- package/slides/introducing-konpeki/composition.json +0 -3270
- package/slides/line-chart/PROMPT.md +0 -40
- package/slides/line-chart/index.tsx +0 -72
- package/slides/migration/PROMPT.md +0 -38
- package/slides/migration/index.tsx +0 -89
- package/slides/og-images/PROMPT.md +0 -21
- package/slides/og-images/index.tsx +0 -76
- package/slides/product-introduction/PROMPT.md +0 -24
- package/slides/product-introduction/index.tsx +0 -105
- package/slides/research-brief/PROMPT.md +0 -40
- package/slides/research-brief/index.tsx +0 -104
- package/slides/results-explanation/PROMPT.md +0 -32
- package/slides/results-explanation/index.tsx +0 -96
- package/slides/retrospective/PROMPT.md +0 -43
- package/slides/retrospective/index.tsx +0 -105
- package/slides/sankey/PROMPT.md +0 -11
- package/slides/sankey/index.tsx +0 -93
- package/slides/teaching/PROMPT.md +0 -45
- package/slides/teaching/index.tsx +0 -124
- package/slides/vertical-bar-charts/PROMPT.md +0 -13
- package/slides/vertical-bar-charts/index.tsx +0 -97
- package/src/app/App.tsx +0 -845
- package/src/components/BuildOrb.tsx +0 -40
- package/src/components/Canvas.tsx +0 -1191
- package/src/components/DiagramTypeIcon.tsx +0 -78
- package/src/components/InspectorPanel.tsx +0 -757
- package/src/components/LeftPanel.tsx +0 -120
- package/src/components/PageSizePicker.tsx +0 -30
- package/src/components/Presentation.tsx +0 -105
- package/src/components/RevisionNotes.tsx +0 -55
- package/src/components/RightPanel.tsx +0 -233
- package/src/components/VectorOverflowWarning.tsx +0 -73
- package/src/components/WorkspaceChrome.tsx +0 -316
- package/src/components/ui.tsx +0 -147
- package/src/lib/examples/react-page-migration.json +0 -1295
- package/src/lib/examples.ts +0 -42
- package/src/lib/export-png.ts +0 -104
- package/src/lib/file-session.ts +0 -87
- package/src/lib/history.ts +0 -53
- package/src/lib/model.ts +0 -188
- package/src/lib/page-size.ts +0 -24
- package/src/lib/presentation.ts +0 -17
- package/src/lib/review.ts +0 -26
- package/src/lib/storage.ts +0 -71
- package/src/lib/theme.ts +0 -25
- package/src/lib/use-file-session.ts +0 -249
- package/src/main.tsx +0 -29
- package/src/styles/canvas.css +0 -299
- package/src/styles/chrome.css +0 -475
- package/src/styles/component-previews.css +0 -386
- package/src/styles/left-panel.css +0 -187
- package/src/styles/presentation.css +0 -72
- package/src/styles/right-panel.css +0 -1298
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import type { ReactNode } from 'react';
|
|
2
|
-
import '@fontsource/newsreader/latin-400.css';
|
|
3
|
-
import '@fontsource/ibm-plex-sans/latin-400.css';
|
|
4
|
-
import '@fontsource/ibm-plex-sans/latin-600.css';
|
|
5
|
-
|
|
6
|
-
const green = '#164D3A';
|
|
7
|
-
const ink = '#202B26';
|
|
8
|
-
const muted = '#526159';
|
|
9
|
-
function Copy({ x = 112, y, lines, size = 36, color = ink, bold = false }: {
|
|
10
|
-
x?: number; y: number; lines: string[]; size?: number; color?: string; bold?: boolean;
|
|
11
|
-
}) {
|
|
12
|
-
return <text x={x} y={y} fill={color} fontSize={size} fontWeight={bold ? 600 : 400}>
|
|
13
|
-
{lines.map((line, i) => <tspan key={i} x={x} dy={i ? size * 1.35 : 0}>{line}</tspan>)}
|
|
14
|
-
</text>;
|
|
15
|
-
}
|
|
16
|
-
function Frame({ number, title, summary, children }: {
|
|
17
|
-
number: number; title: string[]; summary: string; children: ReactNode;
|
|
18
|
-
}) {
|
|
19
|
-
return <svg xmlns="http://www.w3.org/2000/svg" width="1920" height="1080" viewBox="0 0 1920 1080"
|
|
20
|
-
role="img" aria-label={`${title.join(' ')}. ${summary}`} fontFamily="IBM Plex Sans" data-cedar-page={number}>
|
|
21
|
-
<rect width="1920" height="1080" fill="#FFFFFF" />
|
|
22
|
-
<text x="112" y="160" fontFamily="Newsreader" fontSize="82" fill={green}>
|
|
23
|
-
{title.map((line, i) => <tspan key={i} x="112" dy={i ? 90 : 0}>{line}</tspan>)}
|
|
24
|
-
</text>
|
|
25
|
-
{children}
|
|
26
|
-
<text x="1808" y="1024" textAnchor="end" fontSize="28" fill={muted}>{number} / 3</text>
|
|
27
|
-
</svg>;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const Tradeoff = () => <Frame number={1} title={['Suggested replies were faster;', 'quality signals were weaker.']}
|
|
31
|
-
summary="Cedar Support fictional trial, synthetic data. One week, 120 tickets per group. Standard versus suggested replies: median handling time 12 versus 9 minutes; quality passed 108 of 120 (90%) versus 102 of 120 (85%); reopened within seven days of closure 9 of 120 (7.5%) versus 15 of 120 (12.5%). Quality and reopening are separate measures; a passing ticket can reopen. Each rate uses all 120 tickets in its group.">
|
|
32
|
-
<Copy y={335} lines={['Cedar Support · One week · 120 tickets per group']} color={muted} />
|
|
33
|
-
<Copy x={900} y={443} lines={['Standard workflow']} size={32} bold />
|
|
34
|
-
<Copy x={1335} y={443} lines={['Suggested replies']} size={32} color={green} bold />
|
|
35
|
-
<line x1="112" x2="1808" y1="478" y2="478" stroke="#A4B2AA" />
|
|
36
|
-
<Copy y={553} lines={['Median handling time']} />
|
|
37
|
-
<Copy x={900} y={553} lines={['12 min']} size={46} />
|
|
38
|
-
<Copy x={1335} y={553} lines={['9 min']} size={46} color={green} />
|
|
39
|
-
<line x1="112" x2="1808" y1="601" y2="601" stroke="#D7DED9" />
|
|
40
|
-
<Copy y={676} lines={['Passed quality review']} />
|
|
41
|
-
<Copy x={900} y={676} lines={['108 / 120 · 90%']} size={40} />
|
|
42
|
-
<Copy x={1335} y={676} lines={['102 / 120 · 85%']} size={40} color={green} />
|
|
43
|
-
<line x1="112" x2="1808" y1="724" y2="724" stroke="#D7DED9" />
|
|
44
|
-
<Copy y={791} lines={['Reopened within 7 days', 'of closure']} size={34} />
|
|
45
|
-
<Copy x={900} y={791} lines={['9 / 120 · 7.5%']} size={40} />
|
|
46
|
-
<Copy x={1335} y={791} lines={['15 / 120 · 12.5%']} size={40} color={green} />
|
|
47
|
-
<line x1="112" x2="1808" y1="861" y2="861" stroke="#A4B2AA" />
|
|
48
|
-
<Copy y={922} lines={['Quality and reopening are separate measures: a passing ticket can reopen.',
|
|
49
|
-
'Fictional team; synthetic, hand-authored figures—not an actual trial.']} size={30} color={muted} />
|
|
50
|
-
</Frame>;
|
|
51
|
-
|
|
52
|
-
const Evidence = () => <Frame number={2} title={['The pattern warrants a better test,', 'not a causal claim.']}
|
|
53
|
-
summary="The observed median is 3 minutes lower, while quality pass rate is 5 percentage points lower and reopen rate 5 points higher. These are descriptive differences in synthetic data, not causal effects. Assignment was not randomized; ticket difficulty and agent experience were not controlled. There are no raw timing observations, variance estimates or confidence intervals. Medians cannot establish total hours saved. Labor costs and customer satisfaction were not measured.">
|
|
54
|
-
<Copy y={360} lines={['What the comparison shows']} size={38} color={green} bold />
|
|
55
|
-
<Copy y={433} lines={['3 minutes lower median handling time', '5 percentage points lower quality pass rate', '5 percentage points higher reopen rate']} size={37} />
|
|
56
|
-
<Copy x={1035} y={360} lines={['What could explain it']} size={38} color={green} bold />
|
|
57
|
-
<Copy x={1035} y={433} lines={['Assignment was not randomized.', 'Ticket difficulty and agent experience', 'were not controlled.']} size={37} />
|
|
58
|
-
<Copy y={677} lines={['Precision is unknown']} size={38} color={green} bold />
|
|
59
|
-
<Copy y={750} lines={['No raw timing observations, variance', 'estimates or confidence intervals.']} size={37} />
|
|
60
|
-
<Copy x={1035} y={677} lines={['Business impact is unknown']} size={38} color={green} bold />
|
|
61
|
-
<Copy x={1035} y={750} lines={['Medians cannot yield total hours saved.', 'No labor-cost or customer-satisfaction', 'results are available.']} size={37} />
|
|
62
|
-
<Copy y={948} lines={['These are descriptive differences in synthetic data, not estimates of treatment effects.']} size={30} color={muted} />
|
|
63
|
-
</Frame>;
|
|
64
|
-
|
|
65
|
-
const Decision = () => <Frame number={3} title={['Extend with a longer randomized trial', 'and retain human review.']}
|
|
66
|
-
summary="Recommendation to Cedar Support’s operations lead: authorize a longer randomized trial with comparable ticket categories and human review retained, rather than broad rollout. Agree quality and reopen-rate acceptance criteria before starting; no numerical thresholds have been set. Collect raw handling-time observations and both quality measures, retaining seven-day reopening follow-up. Decide whether speed improves while both quality guardrails are met; revise or stop expansion if either fails. These collection and decision details are recommendations, not observed results.">
|
|
67
|
-
<Copy y={347} lines={['Recommendation to Cedar Support’s operations lead']} size={34} color={muted} />
|
|
68
|
-
<Copy y={475} lines={['Before launch']} size={40} color={green} bold />
|
|
69
|
-
<Copy x={650} y={475} lines={['Agree quality and reopen-rate acceptance criteria.', 'No numerical thresholds have been set.']} size={38} />
|
|
70
|
-
<line x1="112" x2="1808" y1="578" y2="578" stroke="#D7DED9" />
|
|
71
|
-
<Copy y={651} lines={['During the trial']} size={40} color={green} bold />
|
|
72
|
-
<Copy x={650} y={651} lines={['Randomize across comparable ticket categories; retain human review.', 'Collect raw handling times and both quality measures.', 'Allow seven-day reopening follow-up after closure.']} size={35} />
|
|
73
|
-
<line x1="112" x2="1808" y1="798" y2="798" stroke="#D7DED9" />
|
|
74
|
-
<Copy y={871} lines={['At the decision']} size={40} color={green} bold />
|
|
75
|
-
<Copy x={650} y={871} lines={['Does speed improve while both quality guardrails are met?', 'Use the results to judge rollout; revise or stop expansion if either fails.']} size={35} />
|
|
76
|
-
<line x1="112" x2="1808" y1="968" y2="968" stroke="#A4B2AA" />
|
|
77
|
-
</Frame>;
|
|
78
|
-
|
|
79
|
-
export const meta = { title: 'Cedar Support — suggested replies decision', createdAt: '2026-09-12T14:00:00Z' };
|
|
80
|
-
export const notes = [
|
|
81
|
-
'All figures are synthetic and supplied in PROMPT.md. Rates use 120 tickets in each group; quality review and reopening are not mutually exclusive.',
|
|
82
|
-
'Differences are arithmetic descriptions only. Non-random assignment and uncontrolled difficulty/experience prevent causal attribution.',
|
|
83
|
-
'The longer randomized trial, comparable categories, human review, and pre-agreed criteria are supplied proposals. Raw-time collection, complete follow-up and the decision sequence are author recommendations. Trial duration, sample size and thresholds require planning; none is invented here.',
|
|
84
|
-
];
|
|
85
|
-
export default [Tradeoff, Evidence, Decision];
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
Make a three-page delivery-plan briefing for the sponsor and delivery team
|
|
2
|
-
at Harbor. Show the original schedule, the current forecast and the decision
|
|
3
|
-
needed now. Make dependencies and release gates clear.
|
|
4
|
-
|
|
5
|
-
Include a baseline-versus-forecast timeline on a shared date axis, distinguishing
|
|
6
|
-
completed work from forecast work. Show dependency arrows and release gates.
|
|
7
|
-
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
Harbor is a fictional membership service moving its member directory to a new
|
|
11
|
-
system. This is a hand-authored status packet as of the end of 14 October 2026.
|
|
12
|
-
The schedule uses Monday–Friday working days, with no holidays in this scenario.
|
|
13
|
-
|
|
14
|
-
Original baseline, agreed 2 October:
|
|
15
|
-
- Import: 5–9 October, owned by data lead Ana.
|
|
16
|
-
- Validation: 12–14 October, owned by QA lead Ben.
|
|
17
|
-
- Staff training: 15–16 October, owned by operations lead Cora.
|
|
18
|
-
- Launch: 19 October, subject to sponsor approval.
|
|
19
|
-
|
|
20
|
-
Actual progress: import started on 5 October and finished on 14 October.
|
|
21
|
-
The input file contained duplicate member identifiers; resolving them delayed
|
|
22
|
-
completion. Import completion does not mean validation has passed. Validation
|
|
23
|
-
and training have not started. Training materials are ready.
|
|
24
|
-
|
|
25
|
-
Dependencies: validation starts after import completion and requires three
|
|
26
|
-
working days. Training starts after validation passes and requires two working
|
|
27
|
-
days. Launch is no earlier than the next working day after training completes.
|
|
28
|
-
No work overlaps these stages in the current plan.
|
|
29
|
-
|
|
30
|
-
Current forecast, assuming no new defects: validation on 15, 16 and 19 October;
|
|
31
|
-
training on 20–21 October; launch on 22 October. These are forecast dates, not
|
|
32
|
-
completed work or a launch commitment.
|
|
33
|
-
|
|
34
|
-
---
|
|
35
|
-
|
|
36
|
-
Validation must reconcile member counts and required fields against the approved
|
|
37
|
-
input and resolve every duplicate identifier. An unresolved discrepancy blocks
|
|
38
|
-
training and launch. The operations lead must confirm staff readiness after
|
|
39
|
-
training; the sponsor then decides whether to release. No validation result is
|
|
40
|
-
available yet.
|
|
41
|
-
|
|
42
|
-
Ask the sponsor to accept the revised forecast and reserve staff for 20–21
|
|
43
|
-
October. If the original date is immovable, the team needs a separate scope
|
|
44
|
-
decision and revised plan; no safe shortcut has been established. Do not present
|
|
45
|
-
skipping validation as a way to recover the schedule.
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import type { ReactNode } from 'react';
|
|
2
|
-
import { fontsReady } from '../../lib/typeface.ts';
|
|
3
|
-
|
|
4
|
-
await fontsReady;
|
|
5
|
-
const ink = '#172B36', muted = '#50616B', accent = '#006B74', line = '#CAD3D7';
|
|
6
|
-
function Label({ x, y, children, size = 32, color = ink, weight = 400 }: { x: number; y: number; children: ReactNode; size?: number; color?: string; weight?: number }) {
|
|
7
|
-
return <text x={x} y={y} fontSize={size} fill={color} fontWeight={weight}>{children}</text>;
|
|
8
|
-
}
|
|
9
|
-
function Frame({ title, subtitle, page, description, children }: { title: string; subtitle: string; page: number; description: string; children: ReactNode }) {
|
|
10
|
-
return <svg xmlns="http://www.w3.org/2000/svg" width="1920" height="1080" viewBox="0 0 1920 1080" fontFamily="IBM Plex Sans" role="img" aria-label={`${title}. ${description}`} data-page={page}>
|
|
11
|
-
<rect width="1920" height="1080" fill="#FFFFFF" />
|
|
12
|
-
<Label x={100} y={140} size={64} weight={600}>{title}</Label>
|
|
13
|
-
<Label x={100} y={207} size={32} color={muted}>{subtitle}</Label>
|
|
14
|
-
{children}
|
|
15
|
-
<Label x={1705} y={1020} size={26} color={muted}>{page} / 3</Label>
|
|
16
|
-
</svg>;
|
|
17
|
-
}
|
|
18
|
-
const x = (day: number) => 440 + (day - 5) * 70;
|
|
19
|
-
function Gate({ day, y }: { day: number; y: number }) {
|
|
20
|
-
return <path d={`M${x(day)} ${y - 12} l12 12 -12 12 -12 -12 Z`} fill="white" stroke={accent} strokeWidth={3} />;
|
|
21
|
-
}
|
|
22
|
-
function Arrow({ from, to, y }: { from: number; to: number; y: number }) {
|
|
23
|
-
return <path d={`M${x(from)} ${y} V${y + 29} H${x(to)} V${y + 82} m-7 -10 7 10 7 -10`} stroke={accent} strokeWidth={3} fill="none" />;
|
|
24
|
-
}
|
|
25
|
-
const Schedule = () => <Frame page={1} title="Launch moves from 19 to 22 October" subtitle="Import is complete. The remaining dates are a forecast, assuming no new defects." description="Shared calendar axis, October 5–22. Baseline agreed October 2: import October 5–9, validation 12–14, training 15–16, launch 19 subject to sponsor approval. Actual import October 5–14. Forecast validation October 15, 16 and 19; training 20–21; launch 22. Arrows connect non-overlapping forecast stages; diamonds mark validation pass, readiness confirmation and sponsor release gates.">
|
|
26
|
-
<rect x={100} y={263} width={38} height={16} fill="none" stroke={muted} strokeWidth={2} />
|
|
27
|
-
<Label x={153} y={282} size={27}>Baseline · agreed 2 Oct</Label>
|
|
28
|
-
<rect x={500} y={263} width={38} height={16} fill={accent} />
|
|
29
|
-
<Label x={553} y={282} size={27}>Completed</Label>
|
|
30
|
-
<rect x={755} y={263} width={38} height={16} fill="none" stroke={accent} strokeDasharray="6 4" strokeWidth={3} />
|
|
31
|
-
<Label x={808} y={282} size={27}>Forecast</Label>
|
|
32
|
-
<path d="M1050 259 l12 12 -12 12 -12 -12 Z" stroke={accent} strokeWidth={3} fill="white" />
|
|
33
|
-
<Label x={1076} y={282} size={27}>Release gate</Label>
|
|
34
|
-
<Label x={1440} y={282} size={27} color={muted}>Shaded = weekend</Label>
|
|
35
|
-
{[10, 11, 17, 18].map(day => <rect key={day} x={x(day)} y={326} width={70} height={499} fill="#F0F3F4" />)}
|
|
36
|
-
{Array.from({ length: 18 }, (_, i) => i + 5).map(day => <g key={day}>
|
|
37
|
-
<Label x={x(day) + 18} y={352} size={26} color={muted}>{day}</Label>
|
|
38
|
-
<line x1={x(day)} x2={x(day)} y1={367} y2={825} stroke="#E6EBED" />
|
|
39
|
-
</g>)}
|
|
40
|
-
<Label x={100} y={320} size={25} color={muted}>October 2026</Label>
|
|
41
|
-
<Label x={100} y={355} size={25} color={muted}>As of end of 14 Oct</Label>
|
|
42
|
-
{[['Import', 'Ana · data lead'], ['Validation', 'Ben · QA lead'], ['Training', 'Cora · operations'], ['Launch', 'Sponsor approval']].map(([stage, owner], i) => <g key={stage}>
|
|
43
|
-
<Label x={100} y={409 + i * 108} size={34} weight={600}>{stage}</Label>
|
|
44
|
-
<Label x={100} y={447 + i * 108} size={26} color={muted}>{owner}</Label>
|
|
45
|
-
<line x1={100} x2={1770} y1={474 + i * 108} y2={474 + i * 108} stroke={line} />
|
|
46
|
-
</g>)}
|
|
47
|
-
{[[5, 10, 389], [12, 15, 497], [15, 17, 605]].map(([a, b, y]) => <rect key={y} x={x(a)} y={y} width={x(b) - x(a)} height={17} fill="white" stroke={muted} strokeWidth={2} />)}
|
|
48
|
-
<path d={`M${x(19) + 35} 711 l10 10 -10 10 -10 -10 Z`} fill="white" stroke={muted} strokeWidth={2} />
|
|
49
|
-
<rect x={x(5)} y={424} width={x(15) - x(5)} height={26} fill={accent} />
|
|
50
|
-
<Label x={x(5) + 18} y={445} size={23} color="white" weight={500}>5–14 Oct · complete</Label>
|
|
51
|
-
{[[15, 17, 532], [19, 20, 532], [20, 22, 640]].map(([a, b, y]) => <rect key={`${a}-${y}`} x={x(a)} y={y} width={x(b) - x(a)} height={26} fill="white" stroke={accent} strokeWidth={3} strokeDasharray="7 4" />)}
|
|
52
|
-
<Arrow from={15} to={15} y={450} />
|
|
53
|
-
<Arrow from={20} to={20} y={558} />
|
|
54
|
-
<Arrow from={22} to={22.5} y={666} />
|
|
55
|
-
<Gate day={20} y={545} /><Gate day={22} y={653} /><Gate day={22.5} y={761} />
|
|
56
|
-
<Label x={100} y={885} size={32} weight={500}>Duplicate member identifiers delayed import completion.</Label>
|
|
57
|
-
<Label x={100} y={931} size={29} color={muted}>Mon–Fri working days; no holidays. No stage overlap. Import complete does not mean validation passed.</Label>
|
|
58
|
-
<Label x={100} y={972} size={25} color={muted}>Diamonds at bar ends mark completion gates; launch diamonds mark release dates.</Label>
|
|
59
|
-
</Frame>;
|
|
60
|
-
|
|
61
|
-
const Gates = () => <Frame page={2} title="Every release gate still needs evidence" subtitle="Validation and training have not started. No validation result is available yet." description="Validation must reconcile member counts and required fields against approved input and resolve every duplicate identifier. An unresolved discrepancy blocks training and launch. Training follows validation pass and lasts two working days. Cora confirms staff readiness after training; sponsor then decides whether to release. Launch no earlier than next working day after training completes.">
|
|
62
|
-
<Label x={100} y={331} size={28} color={muted}>FORECAST STAGE</Label>
|
|
63
|
-
<Label x={670} y={331} size={28} color={muted}>EVIDENCE REQUIRED TO PROCEED</Label>
|
|
64
|
-
<line x1={100} x2={1800} y1={357} y2={357} stroke={line} />
|
|
65
|
-
<Label x={100} y={413} size={38} weight={600}>Validation · Ben</Label>
|
|
66
|
-
<Label x={100} y={461} size={30} color={accent}>15, 16 & 19 Oct · 3 working days</Label>
|
|
67
|
-
<Label x={670} y={413} size={34}>Reconcile member counts and required fields</Label>
|
|
68
|
-
<Label x={670} y={459} size={34}>against approved input; resolve every duplicate ID.</Label>
|
|
69
|
-
<Label x={670} y={511} size={29} color={accent} weight={500}>Any unresolved discrepancy blocks training and launch.</Label>
|
|
70
|
-
<line x1={100} x2={1800} y1={553} y2={553} stroke={line} />
|
|
71
|
-
<Label x={100} y={611} size={38} weight={600}>Staff training · Cora</Label>
|
|
72
|
-
<Label x={100} y={659} size={30} color={accent}>20–21 Oct · 2 working days</Label>
|
|
73
|
-
<Label x={670} y={611} size={34}>Start only after validation passes.</Label>
|
|
74
|
-
<Label x={670} y={657} size={34}>Operations lead confirms staff readiness afterward.</Label>
|
|
75
|
-
<Label x={670} y={709} size={29} color={muted}>Training materials are ready; staff readiness is not yet confirmed.</Label>
|
|
76
|
-
<line x1={100} x2={1800} y1={751} y2={751} stroke={line} />
|
|
77
|
-
<Label x={100} y={809} size={38} weight={600}>Release · Sponsor</Label>
|
|
78
|
-
<Label x={100} y={857} size={30} color={accent}>22 Oct · conditional forecast</Label>
|
|
79
|
-
<Label x={670} y={809} size={34}>Sponsor decides after staff readiness is confirmed.</Label>
|
|
80
|
-
<Label x={670} y={855} size={34}>No earlier than the next working day after training.</Label>
|
|
81
|
-
<line x1={100} x2={1800} y1={901} y2={901} stroke={line} />
|
|
82
|
-
</Frame>;
|
|
83
|
-
|
|
84
|
-
const Decision = () => <Frame page={3} title="Accept the forecast and reserve staff now" subtitle="Sponsor decision requested · Keep the release gates intact." description="Ask sponsor to accept the revised conditional launch forecast for October 22 and reserve staff for training October 20–21. Forecast assumes no new defects and is not a launch commitment. If October 19 is immovable, a separate scope decision and revised plan are needed. No safe shortcut has been established; do not skip validation.">
|
|
85
|
-
<Label x={100} y={367} size={48} weight={600}>Accept 22 October</Label>
|
|
86
|
-
<Label x={100} y={424} size={34}>as the revised launch forecast,</Label>
|
|
87
|
-
<Label x={100} y={470} size={34}>assuming no new defects.</Label>
|
|
88
|
-
<Label x={100} y={540} size={30} color={accent} weight={500}>A forecast, not a launch commitment.</Label>
|
|
89
|
-
<Label x={1010} y={367} size={48} weight={600}>Reserve 20–21 October</Label>
|
|
90
|
-
<Label x={1010} y={424} size={34}>for staff training with Cora.</Label>
|
|
91
|
-
<Label x={1010} y={470} size={34}>Materials are ready.</Label>
|
|
92
|
-
<Label x={1010} y={540} size={30} color={accent} weight={500}>Training starts only after validation passes.</Label>
|
|
93
|
-
<line x1={100} x2={1800} y1={641} y2={641} stroke={line} />
|
|
94
|
-
<Label x={100} y={723} size={42} weight={600}>If 19 October is immovable</Label>
|
|
95
|
-
<Label x={100} y={785} size={36}>The team needs a separate scope decision and a revised plan.</Label>
|
|
96
|
-
<Label x={100} y={846} size={36}>No safe shortcut has been established. Do not skip validation.</Label>
|
|
97
|
-
</Frame>;
|
|
98
|
-
|
|
99
|
-
export default [Schedule, Gates, Decision];
|
|
100
|
-
export const meta = { title: 'Harbor — Delivery plan', createdAt: '2026-09-12T00:00:00Z' };
|
|
101
|
-
export const notes = [
|
|
102
|
-
'Fictional, hand-authored packet as of end of 14 October 2026. Baseline agreed 2 October. Calendar axis is continuous, weekends shaded; forecast validation has no work on 17–18 October. Diamonds occur at stage completion boundaries or the launch date. All future stages and gates are conditional.',
|
|
103
|
-
'Import started 5 October and finished 14 October after duplicate member identifiers were resolved. Import completion is not evidence of validation passing. The validation gate still requires all stated checks.',
|
|
104
|
-
'Request acceptance of the revised forecast and reserve staff, not unconditional release authorization. No safe shortcut has been established for retaining the original launch date.',
|
|
105
|
-
];
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
# React/SVG drawing references
|
|
2
|
-
|
|
3
|
-
These 18 fictional examples preserve the earlier authoring approach: React/SVG
|
|
4
|
-
source, original briefs and reviewed screenshots. Use them for drawing, typography
|
|
5
|
-
and layout techniques; **they cannot be imported directly into the editor**.
|
|
6
|
-
For editable documents, see the [native gallery](README.md).
|
|
7
|
-
|
|
8
|
-
To adapt trusted source, follow the [conversion guide](../docs/development.md#reactsvg-drawing-references)
|
|
9
|
-
and inspect the result in the canvas. These files are not runnable app routes.
|
|
10
|
-
npm includes source and briefs; screenshots remain in the repository and show
|
|
11
|
-
the historical browser renders, not export or cross-application fidelity.
|
|
12
|
-
|
|
13
|
-
| Example / source | Brief | Screenshots |
|
|
14
|
-
| --- | --- | --- |
|
|
15
|
-
| [Patchnote — product introduction](product-introduction/index.tsx) | [Brief](product-introduction/PROMPT.md) | [Images](product-introduction/screenshots/) |
|
|
16
|
-
| [Parcel Relay — architecture and sequence](architecture/index.tsx) | [Brief](architecture/PROMPT.md) | [Images](architecture/screenshots/) |
|
|
17
|
-
| [Fieldnote — experiment](experiment/index.tsx) | [Brief](experiment/PROMPT.md) | [Images](experiment/screenshots/) |
|
|
18
|
-
| [Lantern — incident workflow](incident-workflow/index.tsx) | [Brief](incident-workflow/PROMPT.md) | [Images](incident-workflow/screenshots/) |
|
|
19
|
-
| [Moss — comparison](comparison/index.tsx) | [Brief](comparison/PROMPT.md) | [Images](comparison/screenshots/) |
|
|
20
|
-
| [Juniper — migration](migration/index.tsx) | [Brief](migration/PROMPT.md) | [Images](migration/screenshots/) |
|
|
21
|
-
| [Clearpath — OG images](og-images/index.tsx) | [Brief](og-images/PROMPT.md) | [Images](og-images/screenshots/) |
|
|
22
|
-
| [Alder — article briefing](article-brief/index.tsx) | [Brief](article-brief/PROMPT.md) | [Images](article-brief/screenshots/) |
|
|
23
|
-
| [Waymark — results explanation](results-explanation/index.tsx) | [Brief](results-explanation/PROMPT.md) | [Images](results-explanation/screenshots/) |
|
|
24
|
-
| [Dockline — retrospective](retrospective/index.tsx) | [Brief](retrospective/PROMPT.md) | [Images](retrospective/screenshots/) |
|
|
25
|
-
| [Fern — research and stacked bars](research-brief/index.tsx) | [Brief](research-brief/PROMPT.md) | [Images](research-brief/screenshots/) |
|
|
26
|
-
| [Cedar Support — decision memo](decision-memo/index.tsx) | [Brief](decision-memo/PROMPT.md) | [Images](decision-memo/screenshots/) |
|
|
27
|
-
| [Harbor — delivery plan and Gantt](delivery-plan/index.tsx) | [Brief](delivery-plan/PROMPT.md) | [Images](delivery-plan/screenshots/) |
|
|
28
|
-
| [Folio — teaching](teaching/index.tsx) | [Brief](teaching/PROMPT.md) | [Images](teaching/screenshots/) |
|
|
29
|
-
| [Tide — line chart](line-chart/index.tsx) | [Brief](line-chart/PROMPT.md) | [Images](line-chart/screenshots/) |
|
|
30
|
-
| [Birch — grouped bar chart](bar-chart/index.tsx) | [Brief](bar-chart/PROMPT.md) | [Images](bar-chart/screenshots/) |
|
|
31
|
-
| [Fieldnote — vertical and paired bars](vertical-bar-charts/index.tsx) | [Brief](vertical-bar-charts/PROMPT.md) | [Images](vertical-bar-charts/screenshots/) |
|
|
32
|
-
| [Brook — Sankey chart](sankey/index.tsx) | [Brief](sankey/PROMPT.md) | [Images](sankey/screenshots/) |
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
Make a three-page presentation for the engineering team at Fieldnote explaining
|
|
2
|
-
an experiment with batching search-index updates. Help them weigh indexing
|
|
3
|
-
throughput against how long users wait for a document to become searchable,
|
|
4
|
-
and decide what to test next.
|
|
5
|
-
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
Fieldnote is a fictional document workspace. Its current indexer processes
|
|
9
|
-
document updates individually. The team tested batches of 20 and 100 updates
|
|
10
|
-
against that baseline.
|
|
11
|
-
|
|
12
|
-
Each configuration processed the same fixed set of 60,000 document updates
|
|
13
|
-
on the same machine, starting with an empty queue and an identical index.
|
|
14
|
-
An update's visibility delay runs from submission until the updated document
|
|
15
|
-
appears in search. Each configuration was run once.
|
|
16
|
-
|
|
17
|
-
Individual updates:
|
|
18
|
-
- Total processing time: 300 seconds.
|
|
19
|
-
- Median visibility delay: 1.2 seconds.
|
|
20
|
-
- 95th-percentile visibility delay: 2.4 seconds.
|
|
21
|
-
|
|
22
|
-
Batches of 20:
|
|
23
|
-
- Total processing time: 200 seconds.
|
|
24
|
-
- Median visibility delay: 1.8 seconds.
|
|
25
|
-
- 95th-percentile visibility delay: 4.1 seconds.
|
|
26
|
-
|
|
27
|
-
Batches of 100:
|
|
28
|
-
- Total processing time: 150 seconds.
|
|
29
|
-
- Median visibility delay: 4.9 seconds.
|
|
30
|
-
- 95th-percentile visibility delay: 11.8 seconds.
|
|
31
|
-
|
|
32
|
-
All configurations produced the expected final document versions, with no
|
|
33
|
-
missing updates in the final check. These are synthetic, hand-authored results.
|
|
34
|
-
There are no repeated runs, uncertainty estimates or production measurements.
|
|
35
|
-
|
|
36
|
-
---
|
|
37
|
-
|
|
38
|
-
The team's proposed acceptance criteria are at least 250 updates per second
|
|
39
|
-
and a 95th-percentile visibility delay no greater than 5 seconds.
|
|
40
|
-
|
|
41
|
-
Recommend which configuration deserves a follow-up test. Explain why the
|
|
42
|
-
fastest configuration is not necessarily the best fit. The next experiment
|
|
43
|
-
should repeat the runs and include both sparse arrivals and bursts, since
|
|
44
|
-
a fixed workload does not establish behavior under live traffic.
|
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
import type { ReactNode } from 'react';
|
|
2
|
-
import '@fontsource/ibm-plex-sans/latin-400.css';
|
|
3
|
-
import '@fontsource/ibm-plex-sans/latin-500.css';
|
|
4
|
-
import '@fontsource/ibm-plex-sans/latin-600.css';
|
|
5
|
-
|
|
6
|
-
const ink = '#172B3A';
|
|
7
|
-
const muted = '#52616C';
|
|
8
|
-
const accent = '#096F78';
|
|
9
|
-
const rule = '#B9C4CA';
|
|
10
|
-
const results = [
|
|
11
|
-
{ name: 'Individual', time: 300, median: 1.2, p95: 2.4 },
|
|
12
|
-
{ name: 'Batch of 20', time: 200, median: 1.8, p95: 4.1 },
|
|
13
|
-
{ name: 'Batch of 100', time: 150, median: 4.9, p95: 11.8 },
|
|
14
|
-
];
|
|
15
|
-
|
|
16
|
-
function Copy({ x = 112, y, size = 36, weight = 400, color = ink, children, anchor = 'start' }: {
|
|
17
|
-
x?: number; y: number; size?: number; weight?: number; color?: string;
|
|
18
|
-
children: ReactNode; anchor?: 'start' | 'middle' | 'end';
|
|
19
|
-
}) {
|
|
20
|
-
return <text x={x} y={y} fontSize={size} fontWeight={weight} fill={color} textAnchor={anchor}>{children}</text>;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function Frame({ page, title, description, children }: {
|
|
24
|
-
page: number; title: string; description: string; children: ReactNode;
|
|
25
|
-
}) {
|
|
26
|
-
return <svg xmlns="http://www.w3.org/2000/svg" width="1920" height="1080" viewBox="0 0 1920 1080"
|
|
27
|
-
fontFamily="IBM Plex Sans, sans-serif" role="img" aria-label={`${title}. ${description}`} data-fieldnote-page={page}>
|
|
28
|
-
<rect width="1920" height="1080" fill="#FFFFFF" />
|
|
29
|
-
<Copy y={158} size={68} weight={600}>{title}</Copy>
|
|
30
|
-
{children}
|
|
31
|
-
<Copy x={1808} y={1020} size={28} color={muted} anchor="end">{page} / 3</Copy>
|
|
32
|
-
</svg>;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const Evidence = () => <Frame page={1} title="Batching buys speed at a freshness cost"
|
|
36
|
-
description="Fieldnote is a fictional document workspace. Synthetic, hand-authored results, one run per configuration. The same 60,000 updates ran on the same machine, starting with an empty queue and identical index. Individual: 300 seconds, 200 updates per second, median delay 1.2 seconds, p95 2.4 seconds. Batch of 20: 200 seconds, 300 updates per second, median 1.8 seconds, p95 4.1 seconds. Batch of 100: 150 seconds, 400 updates per second, median 4.9 seconds, p95 11.8 seconds. Visibility delay is submission to search. All final versions were correct, with no missing updates; no repeated runs, uncertainty estimates or production measurements.">
|
|
37
|
-
<Copy y={237} size={36} color={muted}>Fieldnote is a fictional workspace; its indexer handles updates individually.</Copy>
|
|
38
|
-
<Copy y={291} size={36} color={muted}>Same 60,000 updates · same machine · empty queue · identical starting index</Copy>
|
|
39
|
-
|
|
40
|
-
<Copy y={403} size={30} weight={500}>Configuration</Copy>
|
|
41
|
-
<Copy x={770} y={383} size={30} weight={500} anchor="end">Processing</Copy>
|
|
42
|
-
<Copy x={770} y={425} size={30} color={muted} anchor="end">seconds</Copy>
|
|
43
|
-
<Copy x={1090} y={383} size={30} weight={500} anchor="end">Throughput</Copy>
|
|
44
|
-
<Copy x={1090} y={425} size={30} color={muted} anchor="end">updates / sec</Copy>
|
|
45
|
-
<Copy x={1450} y={383} size={30} weight={500} anchor="end">Median delay</Copy>
|
|
46
|
-
<Copy x={1450} y={425} size={30} color={muted} anchor="end">seconds</Copy>
|
|
47
|
-
<Copy x={1808} y={383} size={30} weight={500} anchor="end">95th-percentile delay</Copy>
|
|
48
|
-
<Copy x={1808} y={425} size={30} color={muted} anchor="end">seconds</Copy>
|
|
49
|
-
{[460, 565, 670, 775].map(y => <line key={y} x1={112} x2={1808} y1={y} y2={y} stroke={rule} strokeWidth={2} />)}
|
|
50
|
-
{results.map((r, i) => <g key={r.name}>
|
|
51
|
-
<Copy y={528 + i * 105} size={40} weight={500}>{r.name}</Copy>
|
|
52
|
-
<Copy x={770} y={528 + i * 105} size={42} anchor="end">{r.time}</Copy>
|
|
53
|
-
<Copy x={1090} y={528 + i * 105} size={42} anchor="end">{60000 / r.time}</Copy>
|
|
54
|
-
<Copy x={1450} y={528 + i * 105} size={42} anchor="end">{r.median.toFixed(1)}</Copy>
|
|
55
|
-
<Copy x={1808} y={528 + i * 105} size={42} anchor="end">{r.p95.toFixed(1)}</Copy>
|
|
56
|
-
</g>)}
|
|
57
|
-
<Copy y={832} size={30} color={muted}>Visibility delay: submission → searchable document. Throughput: 60,000 ÷ processing seconds.</Copy>
|
|
58
|
-
<Copy y={884} size={30}>All final document versions matched expectations; no missing updates in the final check.</Copy>
|
|
59
|
-
<Copy y={949} size={30} color={muted}>Synthetic, hand-authored results · one run each · no uncertainty estimates or production measurements</Copy>
|
|
60
|
-
</Frame>;
|
|
61
|
-
|
|
62
|
-
function Bars({ kind, x, width }: { kind: 'rate' | 'delay'; x: number; width: number }) {
|
|
63
|
-
const rate = kind === 'rate';
|
|
64
|
-
const max = rate ? 400 : 12;
|
|
65
|
-
const target = rate ? 250 : 5;
|
|
66
|
-
const thresholdX = x + target / max * width;
|
|
67
|
-
return <g>
|
|
68
|
-
<Copy x={x} y={348} size={38} weight={500}>{rate ? 'Throughput · updates / sec' : '95th-percentile delay · seconds'}</Copy>
|
|
69
|
-
<Copy x={x} y={397} size={30} color={muted}>{rate ? 'At least 250 required' : 'No more than 5 required'}</Copy>
|
|
70
|
-
<line x1={thresholdX} x2={thresholdX} y1={440} y2={762} stroke={ink} strokeDasharray="9 9" strokeWidth={2} />
|
|
71
|
-
{results.map((r, i) => {
|
|
72
|
-
const value = rate ? 60000 / r.time : r.p95;
|
|
73
|
-
const pass = rate ? value >= target : value <= target;
|
|
74
|
-
const y = 468 + i * 110;
|
|
75
|
-
return <g key={r.name}>
|
|
76
|
-
<rect x={x} y={y} width={value / max * width} height={44} fill={i === 1 ? accent : muted} />
|
|
77
|
-
<Copy x={x + width + 24} y={y + 34} size={30} weight={500}>{value}{pass ? ' ✓' : ' ×'}</Copy>
|
|
78
|
-
</g>;
|
|
79
|
-
})}
|
|
80
|
-
<line x1={x} x2={x + width} y1={768} y2={768} stroke={rule} strokeWidth={2} />
|
|
81
|
-
{(rate ? [0, 100, 200, 300, 400] : [0, 3, 6, 9, 12]).map(tick => <g key={tick}>
|
|
82
|
-
<line x1={x + tick / max * width} x2={x + tick / max * width} y1={768} y2={780} stroke={rule} strokeWidth={2} />
|
|
83
|
-
<Copy x={x + tick / max * width} y={820} size={28} anchor="middle" color={muted}>{tick}</Copy>
|
|
84
|
-
</g>)}
|
|
85
|
-
</g>;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const Decision = () => <Frame page={2} title="Batches of 20 deserve the follow-up test"
|
|
89
|
-
description="Only batches of 20 meet both proposed acceptance criteria in these single synthetic runs: at least 250 updates per second and p95 delay no greater than 5 seconds. Individual: 200 updates per second fails throughput, 2.4 seconds passes delay. Batch of 20: 300 and 4.1 both pass. Batch of 100: 400 passes throughput, 11.8 fails delay. The fastest configuration exceeds the delay ceiling by 6.8 seconds. These results support a follow-up test, not a production rollout.">
|
|
90
|
-
<Copy y={237} size={36} color={muted}>Only this configuration meets both proposed criteria in the single-run results.</Copy>
|
|
91
|
-
{results.map((r, i) => <Copy key={r.name} y={502 + i * 110} size={34} weight={i === 1 ? 600 : 400} color={i === 1 ? accent : ink}>{r.name}</Copy>)}
|
|
92
|
-
<Bars kind="rate" x={445} width={485} />
|
|
93
|
-
<Bars kind="delay" x={1170} width={485} />
|
|
94
|
-
<Copy x={112} y={893} size={34}>Batch of 100 is fastest, but its p95 delay exceeds the ceiling by 6.8 seconds.</Copy>
|
|
95
|
-
<Copy x={112} y={949} size={30} color={muted}>Synthetic, one run each. ✓ meets criterion · × misses criterion. This supports testing, not rollout.</Copy>
|
|
96
|
-
</Frame>;
|
|
97
|
-
|
|
98
|
-
const Next = () => <Frame page={3} title="Repeat the runs, then vary the arrival pattern"
|
|
99
|
-
description="Prioritize batches of 20 and retain individual and batch-of-100 controls. Repeat runs under the original fixed-workload conditions and report run-to-run variability rather than selecting the best run. Include sparse arrivals to measure waits for a partial batch, recording the flush policy; include bursts to measure queue growth and recovery. Measure throughput, median and p95 submission-to-search delay, and final-version correctness. A fixed workload does not establish live-traffic behavior. Reassess batches of 20 against at least 250 updates per second under offered load and p95 no greater than 5 seconds; revise batching or flushing and retest if either fails.">
|
|
100
|
-
<Copy y={237} size={36} color={muted}>Prioritize batches of 20; retain individual updates and batches of 100 as controls.</Copy>
|
|
101
|
-
|
|
102
|
-
<Copy y={363} size={42} weight={600}>Repeat the fixed workload</Copy>
|
|
103
|
-
<Copy y={425} size={34}>Keep the machine, starting index and</Copy>
|
|
104
|
-
<Copy y={471} size={34}>60,000 updates comparable. Report</Copy>
|
|
105
|
-
<Copy y={517} size={34}>run-to-run variability, not the best run.</Copy>
|
|
106
|
-
|
|
107
|
-
<Copy x={1000} y={363} size={42} weight={600}>Exercise sparse arrivals and bursts</Copy>
|
|
108
|
-
<Copy x={1000} y={425} size={34}>Sparse: measure waiting for a partial batch;</Copy>
|
|
109
|
-
<Copy x={1000} y={471} size={34}>record the policy for flushing that batch.</Copy>
|
|
110
|
-
<Copy x={1000} y={539} size={34}>Bursts: track queue growth and recovery,</Copy>
|
|
111
|
-
<Copy x={1000} y={585} size={34}>including submission-to-search delay.</Copy>
|
|
112
|
-
|
|
113
|
-
<line x1={112} x2={1808} y1={650} y2={650} stroke={rule} strokeWidth={2} />
|
|
114
|
-
<Copy y={717} size={40} weight={600} color={accent}>Use both gates before advancing</Copy>
|
|
115
|
-
<Copy y={777} size={34}>Recheck ≥250 updates/sec under offered load and p95 delay ≤5 sec;</Copy>
|
|
116
|
-
<Copy y={823} size={34}>track median delay and final-version correctness. If either gate fails, revise</Copy>
|
|
117
|
-
<Copy y={869} size={34}>batching or flushing and retest. Sparse traffic tests freshness, not peak capacity.</Copy>
|
|
118
|
-
<Copy y={949} size={30} color={muted}>The fixed workload does not establish live-traffic behavior. No production measurements exist yet.</Copy>
|
|
119
|
-
</Frame>;
|
|
120
|
-
|
|
121
|
-
export const meta = { title: 'Fieldnote: batching search-index updates' };
|
|
122
|
-
export const notes = [
|
|
123
|
-
'Source: the unchanged PROMPT.md. Fieldnote and all results are fictional. Values are not production evidence.',
|
|
124
|
-
'Recommendation is limited to a follow-up test. Rates are derived from 60,000 updates divided by processing time.',
|
|
125
|
-
'Repeated controls, recording the flush policy and queue recovery are proposed implementation details, not measured findings. No flush policy or repetition count was supplied.',
|
|
126
|
-
];
|
|
127
|
-
export default [Evidence, Decision, Next];
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
# Brief
|
|
2
|
-
|
|
3
|
-
> i'd like a cover image for github repo. build it with konpeki
|
|
4
|
-
|
|
5
|
-
## Adaptation
|
|
6
|
-
|
|
7
|
-
- Assumed a 1280×640 GitHub social preview; unspecified mode resolved to default.
|
|
8
|
-
- Use the existing blue mark, white canvas and IBM Plex Sans. Lead with “Konpeki”
|
|
9
|
-
and “Create clear visuals with your coding agent.”
|
|
10
|
-
- Arrange different canvas sizes on a consistent grid, with white backgrounds
|
|
11
|
-
and text, image, chart, diagram and table motifs. Avoid labels or a single
|
|
12
|
-
workflow that suggests these are the only possible outputs.
|
|
13
|
-
- A generated concept informed placement; the final uses editable text and
|
|
14
|
-
vectors, not a flattened concept image.
|
|
15
|
-
|
|
16
|
-
## Sources
|
|
17
|
-
|
|
18
|
-
- Product: [README](../../README.md) and [workflow](../../docs/workflow.md).
|
|
19
|
-
- Brand: [project mark](../../src/assets/konpeki-mark.png) and bundled IBM Plex
|
|
20
|
-
Sans under its existing font license.
|
|
21
|
-
- Canvas motifs are conceptual, not screenshots.
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
# GitHub repository cover
|
|
2
|
-
|
|
3
|
-
[composition.json](composition.json) holds the editable text and vectors;
|
|
4
|
-
[cover.png](cover.png) is its 1280×640 Konpeki PNG export.
|
|
5
|
-
The varied canvas sizes illustrate possible formats, not a fixed workflow.
|
|
6
|
-
|
|
7
|
-
Open from the repository root, edit, then choose **Export PNG**:
|
|
8
|
-
|
|
9
|
-
```sh
|
|
10
|
-
mise exec -- pnpm konpeki preview slides/github-cover/composition.json
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
Refresh [public/og.png](../../public/og.png) for the playground's social cards.
|
|
14
|
-
Uploading the cover to GitHub's repository social-preview setting is separate.
|
|
15
|
-
|
|
16
|
-
[Brief and sources](PROMPT.md). [author.ts](author.ts) reconstructs the initial
|
|
17
|
-
composition using Node.js and ImageMagick; **it overwrites canvas edits**.
|
|
18
|
-
|
|
19
|
-
Original review: validation, typecheck and build passed; all five components and
|
|
20
|
-
IBM Plex Sans loaded. Inspected the 1280×640 export and a 640×320 copy for alignment,
|
|
21
|
-
clipping and legibility.
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import {execFileSync} from 'node:child_process';
|
|
2
|
-
import {writeFileSync} from 'node:fs';
|
|
3
|
-
import {fileURLToPath} from 'node:url';
|
|
4
|
-
import {assertComposition} from '../../composition/validate.ts';
|
|
5
|
-
import {compositionSchema, type CompositionComponent, type CompositionDocument, type VectorElement} from '../../composition/types.ts';
|
|
6
|
-
|
|
7
|
-
// Reproduce the existing mark's alpha silhouette as editable vector geometry.
|
|
8
|
-
const mask=execFileSync('magick',[fileURLToPath(new URL('../../src/assets/konpeki-mark.png',import.meta.url)),'-alpha','extract','-threshold','50%','-depth','8','gray:-']);
|
|
9
|
-
let outline='';
|
|
10
|
-
for(let y=0;y<128;y++)for(let x=0;x<128;x++){
|
|
11
|
-
if(mask[y*128+x]<128)continue;
|
|
12
|
-
const start=x;
|
|
13
|
-
while(x+1<128&&mask[y*128+x+1]>=128)x++;
|
|
14
|
-
outline+=`M${start} ${y}h${x-start+1}v1H${start}Z`;
|
|
15
|
-
}
|
|
16
|
-
const ink='#202630',blue='#007fb5',lightGray='#b2bdc2';
|
|
17
|
-
const text=(id:string,content:string,x:number,y:number,width:number,height:number,size:number,weight:400|600=600):CompositionComponent=>({
|
|
18
|
-
id,kind:'text-block',content,slotIds:[`${id}-content`],preferredRect:{x,y,width,height},
|
|
19
|
-
textStyle:{size,weight,lineHeight:1.18,color:'ink',font:'heading'},
|
|
20
|
-
appearance:{role:id==='brand'?'title':'body',alignment:'start',border:'none',rule:'none'},
|
|
21
|
-
});
|
|
22
|
-
const elements:VectorElement[]=[
|
|
23
|
-
{id:'cover-frame',kind:'rect',attributes:{x:10,y:8,width:260,height:140,rx:8,fill:'#ffffff',stroke:blue,'stroke-width':2.5}},
|
|
24
|
-
{id:'cover-mark',kind:'rect',attributes:{x:28,y:28,width:42,height:42,rx:4,fill:blue}},
|
|
25
|
-
{id:'cover-title',kind:'rect',attributes:{x:86,y:29,width:144,height:13,rx:3,fill:lightGray}},
|
|
26
|
-
{id:'cover-copy-1',kind:'rect',attributes:{x:86,y:53,width:112,height:7,rx:3,fill:lightGray}},
|
|
27
|
-
{id:'cover-copy-2',kind:'rect',attributes:{x:28,y:102,width:164,height:7,rx:3,fill:lightGray}},
|
|
28
|
-
{id:'cover-accent',kind:'rect',attributes:{x:211,y:96,width:39,height:28,rx:4,fill:'#eaf6fb'}},
|
|
29
|
-
{id:'square-frame',kind:'rect',attributes:{x:292,y:8,width:140,height:140,rx:8,fill:'#ffffff',stroke:blue,'stroke-width':2.5}},
|
|
30
|
-
{id:'square-title',kind:'rect',attributes:{x:311,y:28,width:82,height:10,rx:3,fill:lightGray}},
|
|
31
|
-
{id:'square-bar-1',kind:'rect',attributes:{x:314,y:93,width:18,height:31,rx:3,fill:blue}},
|
|
32
|
-
{id:'square-bar-2',kind:'rect',attributes:{x:342,y:72,width:18,height:52,rx:3,fill:'#5cb9df'}},
|
|
33
|
-
{id:'square-bar-3',kind:'rect',attributes:{x:370,y:52,width:18,height:72,rx:3,fill:'#9adbed'}},
|
|
34
|
-
{id:'square-baseline',kind:'path',attributes:{d:'M307 126H410',fill:'none',stroke:lightGray,'stroke-width':2}},
|
|
35
|
-
{id:'portrait-frame',kind:'rect',attributes:{x:10,y:172,width:145,height:230,rx:8,fill:'#ffffff',stroke:blue,'stroke-width':2.5}},
|
|
36
|
-
{id:'portrait-title',kind:'rect',attributes:{x:28,y:193,width:94,height:11,rx:3,fill:lightGray}},
|
|
37
|
-
{id:'portrait-visual',kind:'rect',attributes:{x:28,y:224,width:109,height:81,rx:5,fill:'#eaf6fb'}},
|
|
38
|
-
{id:'portrait-rule',kind:'path',attributes:{d:'M45 285L76 247 96 270 122 236',fill:'none',stroke:blue,'stroke-width':4}},
|
|
39
|
-
{id:'portrait-copy-1',kind:'rect',attributes:{x:28,y:326,width:92,height:7,rx:3,fill:lightGray}},
|
|
40
|
-
{id:'portrait-copy-2',kind:'rect',attributes:{x:28,y:344,width:108,height:7,rx:3,fill:lightGray}},
|
|
41
|
-
{id:'portrait-copy-3',kind:'rect',attributes:{x:28,y:362,width:74,height:7,rx:3,fill:lightGray}},
|
|
42
|
-
{id:'slide-frame',kind:'rect',attributes:{x:180,y:172,width:252,height:144,rx:8,fill:'#ffffff',stroke:blue,'stroke-width':2.5}},
|
|
43
|
-
{id:'slide-title',kind:'rect',attributes:{x:199,y:190,width:115,height:11,rx:3,fill:lightGray}},
|
|
44
|
-
{id:'diagram-path',kind:'path',attributes:{d:'M305 251V270H231V278M305 270H379V278',fill:'none',stroke:lightGray,'stroke-width':3}},
|
|
45
|
-
{id:'diagram-parent',kind:'rect',attributes:{x:284,y:215,width:42,height:36,rx:7,fill:blue}},
|
|
46
|
-
{id:'diagram-child-1',kind:'rect',attributes:{x:210,y:278,width:42,height:25,rx:6,fill:'#eaf6fb',stroke:blue,'stroke-width':2}},
|
|
47
|
-
{id:'diagram-child-2',kind:'rect',attributes:{x:358,y:278,width:42,height:25,rx:6,fill:'#eaf6fb',stroke:blue,'stroke-width':2}},
|
|
48
|
-
{id:'table-frame',kind:'rect',attributes:{x:180,y:338,width:252,height:64,rx:8,fill:'#ffffff',stroke:blue,'stroke-width':2.5}},
|
|
49
|
-
{id:'table-header',kind:'rect',attributes:{x:181,y:339,width:250,height:20,rx:7,fill:'#eaf6fb'}},
|
|
50
|
-
{id:'table-grid',kind:'path',attributes:{d:'M250 339V401M330 339V401M181 359H431M181 380H431',fill:'none',stroke:lightGray,'stroke-width':2}},
|
|
51
|
-
{id:'table-emphasis',kind:'rect',attributes:{x:196,y:365,width:38,height:8,rx:3,fill:blue}},
|
|
52
|
-
];
|
|
53
|
-
const components:CompositionComponent[]=[
|
|
54
|
-
text('brand','Konpeki',150,120,480,110,84),
|
|
55
|
-
{id:'brand-mark',kind:'image',slotIds:['brand-mark-content'],preferredRect:{x:64,y:143,width:66,height:66},customVisual:{format:'vector',viewBox:{x:0,y:0,width:128,height:128},description:'Konpeki blue brush mark',elements:[{id:'mark-silhouette',kind:'path',attributes:{d:outline,fill:blue}}]}},
|
|
56
|
-
text('promise','Create clear visuals',64,302,680,90,62),
|
|
57
|
-
text('audience','with your coding agent.',64,400,660,76,44,400),
|
|
58
|
-
{id:'visual-family',kind:'image',slotIds:['visual-family-content'],preferredRect:{x:772,y:106,width:444,height:412},customVisual:{format:'vector',viewBox:{x:0,y:0,width:444,height:412},description:'Aligned white canvases using Konpeki text, image, bar chart, line chart, diagram and table components.',elements}},
|
|
59
|
-
];
|
|
60
|
-
const document:CompositionDocument={schema:compositionSchema,title:'Konpeki GitHub cover',authoringMode:'default',theme:{id:'plex',mode:'paper'},slides:[{
|
|
61
|
-
id:'github-cover',name:'GitHub repository cover',canvas:{width:1280,height:640},innerPadding:{top:64,right:64,bottom:64,left:64},pageNumber:{style:'none',color:'muted'},
|
|
62
|
-
audience:'Developers discovering Konpeki on GitHub',question:'What can I create with Konpeki and my coding agent?',intendedViewingSize:'social',components,
|
|
63
|
-
contentSlots:components.map(c=>({id:c.slotIds[0],label:c.id,role:'body',required:true,instruction:c.kind==='text-block'?c.content??'':c.customVisual?.description??''})),
|
|
64
|
-
groups:[],relationships:[],readingOrder:components.map(c=>({kind:'component',id:c.id})),paintOrder:components.map(c=>c.id),
|
|
65
|
-
}]};
|
|
66
|
-
assertComposition(document);
|
|
67
|
-
writeFileSync(new URL('composition.json',import.meta.url),JSON.stringify(document,null,2)+'\n');
|