@litfamily/litmuse 0.1.1 → 0.1.3
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/CHANGELOG.md +21 -0
- package/README.md +23 -1
- package/README_ko-KR.md +23 -1
- package/TRADEMARK.md +12 -0
- package/bin/litmuse.mjs +4 -0
- package/lib/stage-card.mjs +249 -6
- package/package.json +3 -2
- package/plugin/.muse-plugin/plugin.json +26 -11
- package/plugin/commands/lit-status.md +3 -1
- package/plugin/commands/lit.md +1 -1
- package/plugin/hooks/lib/digest.mjs +1 -1
- package/plugin/hooks/lib/next-step.mjs +112 -0
- package/plugin/hooks/lib/routes.mjs +59 -0
- package/plugin/hooks/lib/stage.mjs +53 -6
- package/plugin/hooks/lib/workflow-stack.mjs +336 -0
- package/plugin/hooks/post-tool-use-failure.mjs +2 -0
- package/plugin/hooks/post-tool-use.mjs +2 -0
- package/plugin/hooks/session-end.mjs +2 -1
- package/plugin/hooks/session-start.mjs +32 -2
- package/plugin/hooks/stop.mjs +23 -3
- package/plugin/hooks/user-prompt-submit.mjs +138 -7
- package/plugin/lib/capped-fetch.mjs +25 -0
- package/plugin/lib/pinned-fetch.mjs +79 -0
- package/plugin/lib/plan-task-rows.mjs +32 -0
- package/plugin/lib/render_pages.py +29 -1
- package/plugin/lib/rewind/collect.mjs +808 -0
- package/plugin/lib/rewind/gauge.mjs +72 -0
- package/plugin/lib/rewind/next-step.mjs +91 -0
- package/plugin/lib/rewind/redact.mjs +83 -0
- package/plugin/lib/rewind/transcripts.mjs +229 -0
- package/plugin/skills/frontend-ui-ux/SKILL.md +24 -9
- package/plugin/skills/frontend-ui-ux/kit/components.css +414 -0
- package/plugin/skills/frontend-ui-ux/kit/fonts.json +22 -0
- package/plugin/skills/frontend-ui-ux/kit/layouts/landing.html +164 -0
- package/plugin/skills/frontend-ui-ux/kit/layouts/settings.html +114 -0
- package/plugin/skills/frontend-ui-ux/kit/layouts/workspace.html +115 -0
- package/plugin/skills/frontend-ui-ux/kit/styles/computational-brutalism.json +227 -0
- package/plugin/skills/frontend-ui-ux/kit/styles/field-notes.json +205 -0
- package/plugin/skills/frontend-ui-ux/kit/styles/graphite.json +200 -0
- package/plugin/skills/frontend-ui-ux/kit/styles/meadow.json +199 -0
- package/plugin/skills/frontend-ui-ux/kit/styles/neo-brutalism.json +222 -0
- package/plugin/skills/frontend-ui-ux/kit/ui.js +226 -0
- package/plugin/skills/frontend-ui-ux/references/complete-contract.md +2 -1
- package/plugin/skills/frontend-ui-ux/references/craft-floor.md +9 -4
- package/plugin/skills/frontend-ui-ux/references/default-editorial-pixel.json +59 -7
- package/plugin/skills/frontend-ui-ux/references/house-styles.md +234 -0
- package/plugin/skills/frontend-ui-ux/references/motion-guide.md +3 -3
- package/plugin/skills/frontend-ui-ux/references/slop-register.md +7 -7
- package/plugin/skills/frontend-ui-ux/scripts/design-lock.mjs +400 -0
- package/plugin/skills/frontend-ui-ux/scripts/interface-probe-lock.mjs +196 -0
- package/plugin/skills/frontend-ui-ux/scripts/interface-probe-page.mjs +31 -10
- package/plugin/skills/frontend-ui-ux/scripts/interface-probe-rules.mjs +19 -7
- package/plugin/skills/frontend-ui-ux/scripts/interface-probe-static.mjs +4 -0
- package/plugin/skills/frontend-ui-ux/scripts/interface-probe.mjs +59 -7
- package/plugin/skills/frontend-ui-ux/scripts/pixel-art.mjs +60 -0
- package/plugin/skills/lit-adhd/SKILL.md +195 -0
- package/plugin/skills/lit-adhd/references/card-examples.md +121 -0
- package/plugin/skills/lit-adhd/references/status-taxonomy.md +45 -0
- package/plugin/skills/lit-adhd/scripts/rewind.mjs +11 -0
- package/plugin/skills/lit-diagram-drawer/SKILL.md +3 -3
- package/plugin/skills/lit-diagram-drawer/scripts/diagram-craft-rules.mjs +1 -2
- package/plugin/skills/lit-diagram-drawer/scripts/visual-quality.mjs +0 -1
- package/plugin/skills/lit-docx/SKILL.md +1 -1
- package/plugin/skills/lit-hijack/SKILL.md +589 -0
- package/plugin/skills/lit-hijack/references/capture-and-provenance.md +123 -0
- package/plugin/skills/lit-hijack/references/clean-room-build.md +133 -0
- package/plugin/skills/lit-hijack/references/distil-and-licence.md +128 -0
- package/plugin/skills/lit-hijack/references/gap-and-port-design.md +152 -0
- package/plugin/skills/lit-hijack/references/parity-and-report.md +133 -0
- package/plugin/skills/lit-hijack/scripts/hijack.mjs +879 -0
- package/plugin/skills/lit-plan/SKILL.md +12 -1
- package/plugin/skills/lit-plan/scripts/check-plan.mjs +71 -4
- package/plugin/skills/lit-pptx/SKILL.md +20 -9
- package/plugin/skills/lit-pptx/fonts/jetbrains-mono/JetBrainsMono-Bold.ttf +0 -0
- package/plugin/skills/lit-pptx/fonts/jetbrains-mono/JetBrainsMono-Regular.ttf +0 -0
- package/plugin/skills/lit-pptx/fonts/jetbrains-mono/OFL.txt +93 -0
- package/plugin/skills/lit-pptx/fonts/provenance.json +32 -1
- package/plugin/skills/lit-pptx/references/direction-step.md +19 -2
- package/plugin/skills/lit-pptx/references/examples/13-engineering-review-computational-brutalism-ko.md +173 -0
- package/plugin/skills/lit-pptx/references/examples/14-launch-pitch-neo-brutalism-ko.md +154 -0
- package/plugin/skills/lit-pptx/references/examples/15-design-lecture-bauhaus-ko.md +139 -0
- package/plugin/skills/lit-pptx/references/examples/16-community-programme-riso-ko.md +158 -0
- package/plugin/skills/lit-pptx/references/examples/17-public-data-briefing-newsroom-ko.md +179 -0
- package/plugin/skills/lit-pptx/references/tonalities/bauhaus.md +112 -0
- package/plugin/skills/lit-pptx/references/tonalities/computational-brutalism.md +118 -0
- package/plugin/skills/lit-pptx/references/tonalities/neo-brutalism.md +125 -0
- package/plugin/skills/lit-pptx/references/tonalities/newsroom.md +115 -0
- package/plugin/skills/lit-pptx/references/tonalities/riso.md +109 -0
- package/plugin/skills/lit-pptx/scripts/compile-deck.js +1 -1
- package/plugin/skills/lit-pptx/scripts/craft_extras.py +136 -92
- package/plugin/skills/lit-pptx/scripts/embed_fonts.py +13 -1
- package/plugin/skills/lit-pptx/scripts/lib/grid-resolver.js +105 -116
- package/plugin/skills/lit-pptx/scripts/lib/layout-resolver.js +9 -15
- package/plugin/skills/lit-pptx/scripts/lib/render-pack.js +368 -561
- package/plugin/skills/lit-pptx/scripts/lib/slide-grid.js +104 -0
- package/plugin/skills/lit-pptx/scripts/lib/template-registry.js +57 -6
- package/plugin/skills/lit-pptx/scripts/qa_deck.py +4 -4
- package/plugin/skills/lit-pptx/templates/tonalities/atlas/pack.yaml +1 -1
- package/plugin/skills/lit-pptx/templates/tonalities/bauhaus/pack.yaml +98 -0
- package/plugin/skills/lit-pptx/templates/tonalities/chalk/pack.yaml +1 -1
- package/plugin/skills/lit-pptx/templates/tonalities/computational-brutalism/pack.yaml +99 -0
- package/plugin/skills/lit-pptx/templates/tonalities/gazette/pack.yaml +1 -1
- package/plugin/skills/lit-pptx/templates/tonalities/ledger/pack.yaml +1 -1
- package/plugin/skills/lit-pptx/templates/tonalities/neo-brutalism/pack.yaml +107 -0
- package/plugin/skills/lit-pptx/templates/tonalities/newsroom/pack.yaml +99 -0
- package/plugin/skills/lit-pptx/templates/tonalities/night/pack.yaml +1 -1
- package/plugin/skills/lit-pptx/templates/tonalities/paper/pack.yaml +1 -1
- package/plugin/skills/lit-pptx/templates/tonalities/riso/pack.yaml +99 -0
- package/plugin/skills/lit-pptx/templates/tonalities/signal/pack.yaml +2 -2
- package/plugin/skills/lit-pptx/templates/tonalities/studio/pack.yaml +1 -1
- package/plugin/skills/lit-recap/SKILL.md +3 -0
- package/plugin/skills/lit-schematic/SKILL.md +241 -0
- package/plugin/skills/lit-schematic/examples/iso-heat-exchanger/build.mjs +14 -0
- package/plugin/skills/lit-schematic/examples/iso-heat-exchanger/scene.mjs +8 -0
- package/plugin/skills/lit-schematic/examples/journal-adsorption-rig/build.mjs +22 -0
- package/plugin/skills/lit-schematic/examples/pid-dosing-skid/build.mjs +73 -0
- package/plugin/skills/lit-schematic/references/cutaway-outputs.md +25 -0
- package/plugin/skills/lit-schematic/references/isometric-craft.md +24 -0
- package/plugin/skills/lit-schematic/references/journal-figures.md +19 -0
- package/plugin/skills/lit-schematic/references/kit-api.md +27 -0
- package/plugin/skills/lit-schematic/references/pfd-and-layout.md +20 -0
- package/plugin/skills/lit-schematic/references/pid-drafting.md +26 -0
- package/plugin/skills/lit-schematic/references/pid-symbols.md +27 -0
- package/plugin/skills/lit-schematic/references/verification.md +24 -0
- package/plugin/skills/lit-schematic/scripts/doctor.mjs +13 -0
- package/plugin/skills/lit-schematic/scripts/lib/figure.mjs +49 -0
- package/plugin/skills/lit-schematic/scripts/lib/isa.mjs +18 -0
- package/plugin/skills/lit-schematic/scripts/lib/iso.mjs +58 -0
- package/plugin/skills/lit-schematic/scripts/lib/legend-sheet.mjs +10 -0
- package/plugin/skills/lit-schematic/scripts/lib/qa-core.mjs +241 -0
- package/plugin/skills/lit-schematic/scripts/lib/sheet.mjs +446 -0
- package/plugin/skills/lit-schematic/scripts/lib/svg.mjs +39 -0
- package/plugin/skills/lit-schematic/scripts/lib/theme.mjs +25 -0
- package/plugin/skills/lit-schematic/scripts/motion.mjs +8 -0
- package/plugin/skills/lit-schematic/scripts/qa.mjs +21 -0
- package/plugin/skills/lit-schematic/scripts/render.mjs +38 -0
- package/plugin/skills/lit-schematic/scripts/scaffold.mjs +73 -0
- package/plugin/skills/lit-scientific-visualization/SKILL.md +2 -0
- package/plugin/skills/lit-team/scripts/state-root.mjs +5 -18
- package/plugin/skills/lit-typographic-motion/SKILL.md +12 -8
- package/plugin/skills/lit-typographic-motion/engine/THIRD_PARTY_NOTICES +11 -0
- package/plugin/skills/lit-typographic-motion/engine/blender/runner.py +218 -0
- package/plugin/skills/lit-typographic-motion/engine/core/presets.mjs +1 -1
- package/plugin/skills/lit-typographic-motion/engine/node/assets.mjs +218 -0
- package/plugin/skills/lit-typographic-motion/engine/node/blender.mjs +144 -0
- package/plugin/skills/lit-typographic-motion/engine/node/board.mjs +136 -0
- package/plugin/skills/lit-typographic-motion/engine/node/done.mjs +42 -3
- package/plugin/skills/lit-typographic-motion/engine/node/gallery.mjs +120 -0
- package/plugin/skills/lit-typographic-motion/engine/node/house.mjs +44 -0
- package/plugin/skills/lit-typographic-motion/engine/node/pipeline.mjs +18 -7
- package/plugin/skills/lit-typographic-motion/engine/node/runtime.mjs +6 -3
- package/plugin/skills/lit-typographic-motion/engine/node/scaffold.mjs +210 -0
- package/plugin/skills/lit-typographic-motion/engine/node/score.mjs +639 -0
- package/plugin/skills/lit-typographic-motion/engine/node/sound-cli.mjs +21 -4
- package/plugin/skills/lit-typographic-motion/engine/node/sound.mjs +126 -27
- package/plugin/skills/lit-typographic-motion/engine/node/stage-serve.mjs +29 -5
- package/plugin/skills/lit-typographic-motion/engine/node/stage.mjs +82 -14
- package/plugin/skills/lit-typographic-motion/engine/node/styles.mjs +214 -0
- package/plugin/skills/lit-typographic-motion/engine/node/treatment.mjs +311 -10
- package/plugin/skills/lit-typographic-motion/engine/vendor/three/LICENSE +21 -0
- package/plugin/skills/lit-typographic-motion/engine/vendor/three/addons/environments/RoomEnvironment.js +144 -0
- package/plugin/skills/lit-typographic-motion/engine/vendor/three/addons/geometries/RoundedBoxGeometry.js +155 -0
- package/plugin/skills/lit-typographic-motion/engine/vendor/three/three.module.js +54571 -0
- package/plugin/skills/lit-typographic-motion/recipes/hero-3d/expected.json +69 -0
- package/plugin/skills/lit-typographic-motion/recipes/hero-3d/index.html +139 -0
- package/plugin/skills/lit-typographic-motion/references/depth.md +122 -0
- package/plugin/skills/lit-typographic-motion/references/sound.md +74 -16
- package/plugin/skills/lit-typographic-motion/references/stage.md +29 -5
- package/plugin/skills/lit-typographic-motion/references/studio.md +245 -0
- package/plugin/skills/lit-typographic-motion/references/treatment.md +31 -8
- package/plugin/skills/lit-typographic-motion/scripts/motion.mjs +48 -7
- package/plugin/skills/lit-typographic-motion/styles/paper.json +41 -0
- package/plugin/skills/lit-typographic-motion/styles/swiss-signal.json +41 -0
- package/plugin/skills/lit-typographic-motion/styles/terminalcore.json +42 -0
- package/plugin/skills/lit-typographic-motion/styles/tidal.json +41 -0
- package/plugin/skills/readme-studio/SKILL.md +1 -1
- package/plugin/skills/start-work/SKILL.md +10 -1
|
@@ -169,6 +169,17 @@ Detail earns its place when it removes executor judgment, protects a boundary or
|
|
|
169
169
|
8. The final verification wave.
|
|
170
170
|
9. Commit strategy, success criteria, DoneClaim, risks and open questions.
|
|
171
171
|
|
|
172
|
+
### Scope roots for outside folders
|
|
173
|
+
|
|
174
|
+
When a todo names an absolute path outside the project (a shared notes folder, a sibling checkout, a temp area), the plan grants it before the work starts, with one line per folder anywhere outside a code fence:
|
|
175
|
+
|
|
176
|
+
```text
|
|
177
|
+
Scope roots: /abs/path/to/folder (read)
|
|
178
|
+
Scope roots: /abs/path/to/scratch (read, write, execute)
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Grant the narrowest existing folder and only the actions the todos need. Paths inside the project need no line. A command quoted in a fence or an inline code span (it holds a space) is data and needs no line; a code span that is one bare path counts. Before saving, search the Todos for `/` paths and add the missing lines. `start-work` runs `node scripts/check-plan.mjs --check plans/<slug>.md`, which fails on an uncovered folder and prints the exact line to add; a filesystem-root, top-level or home folder is never suggested, so name a narrower one.
|
|
182
|
+
|
|
172
183
|
A task that builds or changes a user-facing web interface names `frontend-ui-ux` in its verification (the interface probe across the responsive matrix, with no HIGH finding left) and hands the acceptance verdict to `visual-qa`. A CLI, library or backend-only task names neither.
|
|
173
184
|
|
|
174
185
|
### Plan-row grammar (machine-checkable)
|
|
@@ -337,7 +348,7 @@ Refused on this route: `create_goal`, `update_goal`, `write_todos`, `add_memory`
|
|
|
337
348
|
|
|
338
349
|
Stop when the plan file is written and passes the checklist, or when a missing answer blocks every useful task (then the plan carries the question as row 1 and the reply says `BLOCKED: <question>`). After two failed attempts at one section, surface what you tried and ask.
|
|
339
350
|
|
|
340
|
-
Reply in reader form: the plan path, the TL;DR, the number of tasks, any assumption the user should confirm, and the next action:
|
|
351
|
+
Reply in reader form: the plan path, the TL;DR, the number of tasks, any assumption the user should confirm, and the next action. End the reply with this line, plan name filled in: "Type `go` within 30 minutes to start `plans/<slug>.md` with start-work, or run `/start-work` later." The Stop hook records the saved plan for this session only, so `go` from another session, or after 30 minutes, starts nothing. Approval covers plan generation; implementation, commit, push, versioning and publishing each need their own go-ahead. Keep logs, lane verdicts and command lists in the draft and ledger unless the user asks for them.
|
|
341
352
|
|
|
342
353
|
## Pitfalls
|
|
343
354
|
|
|
@@ -10,8 +10,9 @@
|
|
|
10
10
|
// Exit 0 = pass, 1 = findings, 2 = usage. A planning turn cannot run this (the route policy refuses node);
|
|
11
11
|
// start-work, a terminal and the test suite do.
|
|
12
12
|
|
|
13
|
-
import { existsSync, lstatSync, readFileSync } from 'node:fs';
|
|
14
|
-
import {
|
|
13
|
+
import { existsSync, lstatSync, readFileSync, realpathSync, statSync } from 'node:fs';
|
|
14
|
+
import { homedir } from 'node:os';
|
|
15
|
+
import { basename, dirname, isAbsolute, join, relative, resolve } from 'node:path';
|
|
15
16
|
import { fileURLToPath } from 'node:url';
|
|
16
17
|
|
|
17
18
|
export const SLUG_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/u;
|
|
@@ -56,7 +57,67 @@ export function visibleLines(text) {
|
|
|
56
57
|
return out;
|
|
57
58
|
}
|
|
58
59
|
|
|
59
|
-
|
|
60
|
+
// `Scope roots: <path> (<action>, <action>)`: an outside folder the plan's todos reach, granted up front.
|
|
61
|
+
export const SCOPE_ROOT_LINE = /^Scope roots?:[ \t]*(\S+)[ \t]*\(([a-z, -]+)\)[ \t]*$/u;
|
|
62
|
+
// An absolute path with at least two segments. Inside an inline code span only a span that is one bare
|
|
63
|
+
// path counts; a span holding spaces is a quoted command, which is data rather than a folder.
|
|
64
|
+
const ABSOLUTE_PATH = /(?<![\w.~/-])\/[\w.@+%,=~-]+(?:\/[\w.@+%,=~-]+)+\/?/gu;
|
|
65
|
+
const pathsIn = (line) => line
|
|
66
|
+
.replace(/`([^`]*)`/gu, (_, span) => (/\s/u.test(span.trim()) ? ' ' : ` ${span.trim()} `))
|
|
67
|
+
.match(ABSOLUTE_PATH) ?? [];
|
|
68
|
+
|
|
69
|
+
const realOr = (path) => {
|
|
70
|
+
try {
|
|
71
|
+
return realpathSync(path);
|
|
72
|
+
} catch {
|
|
73
|
+
return path;
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
const within = (root, path) => {
|
|
77
|
+
const rel = relative(root, path);
|
|
78
|
+
return rel === '' || (!rel.startsWith('..') && !isAbsolute(rel));
|
|
79
|
+
};
|
|
80
|
+
const existingFolder = (path) => {
|
|
81
|
+
for (let at = path; ; at = dirname(at)) {
|
|
82
|
+
try {
|
|
83
|
+
if (statSync(at).isDirectory()) return at;
|
|
84
|
+
} catch { /* not there: climb */ }
|
|
85
|
+
if (dirname(at) === at) return at;
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Absolute paths named under `## Todos` (up to `## Final verification wave`, fences skipped) that lie
|
|
91
|
+
* outside `projectRoot` and outside every `Scope roots:` line, one entry per folder: `{path, suggestion}`
|
|
92
|
+
* with the line to add, or `{path, problem}` when the nearest existing folder is too broad to grant.
|
|
93
|
+
*/
|
|
94
|
+
export function uncoveredScopePaths(text, projectRoot) {
|
|
95
|
+
const project = realOr(resolve(projectRoot));
|
|
96
|
+
const lines = visibleLines(text);
|
|
97
|
+
const granted = lines.map(({ line }) => SCOPE_ROOT_LINE.exec(line.trim())).filter(Boolean)
|
|
98
|
+
.map(([, path]) => realOr(isAbsolute(path) ? path : resolve(project, path)));
|
|
99
|
+
const found = new Map();
|
|
100
|
+
let todos = false;
|
|
101
|
+
for (const { line } of lines) {
|
|
102
|
+
const heading = line.trimEnd();
|
|
103
|
+
if (heading === '## Todos') todos = true;
|
|
104
|
+
else if (/^## /u.test(heading)) todos = false;
|
|
105
|
+
if (!todos) continue;
|
|
106
|
+
for (const raw of pathsIn(line)) {
|
|
107
|
+
const path = raw.replace(/[.,:;)]+$/u, '');
|
|
108
|
+
const folder = realOr(existingFolder(path));
|
|
109
|
+
const covered = [realOr(path), folder].some((p) => within(project, p) || granted.some((root) => within(root, p)));
|
|
110
|
+
if (covered || found.has(folder)) continue;
|
|
111
|
+
const tooBroad = dirname(folder) === dirname(dirname(folder)) || folder === realOr(homedir());
|
|
112
|
+
found.set(folder, tooBroad
|
|
113
|
+
? { path, problem: `${path} is outside the project; name a narrower existing folder on a Scope roots line` }
|
|
114
|
+
: { path, suggestion: `Scope roots: ${folder} (read)` });
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return [...found.values()];
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function checkPlan(text, { complete = false, projectRoot = null } = {}) {
|
|
60
121
|
const problems = [];
|
|
61
122
|
const lines = visibleLines(text);
|
|
62
123
|
|
|
@@ -115,6 +176,10 @@ export function checkPlan(text, { complete = false } = {}) {
|
|
|
115
176
|
|
|
116
177
|
if (/<fill\b/u.test(text)) problems.push('unfilled <fill ...> placeholders remain: the plan is not decision-complete');
|
|
117
178
|
|
|
179
|
+
if (projectRoot) {
|
|
180
|
+
for (const entry of uncoveredScopePaths(text, projectRoot)) problems.push(entry.problem ?? `${entry.path} is outside the project and no Scope roots line covers it; add: ${entry.suggestion}`);
|
|
181
|
+
}
|
|
182
|
+
|
|
118
183
|
if (complete) {
|
|
119
184
|
for (const { line } of marked) {
|
|
120
185
|
if (/^- \[ \] /u.test(line)) problems.push(`row still open: ${line.trim()}`);
|
|
@@ -138,7 +203,9 @@ function checkFile(planPath, options) {
|
|
|
138
203
|
}
|
|
139
204
|
if (stat.isSymbolicLink() || !stat.isFile()) return fail(`FAIL PLAN_UNSAFE: ${path} must be a regular file`);
|
|
140
205
|
if (stat.size > MAX_PLAN_BYTES) return fail(`FAIL PLAN_TOO_LARGE: ${path}`);
|
|
141
|
-
|
|
206
|
+
// The project is the folder holding plans/; a plan kept elsewhere is checked against the cwd.
|
|
207
|
+
const projectRoot = basename(dirname(path)) === 'plans' ? dirname(dirname(path)) : process.cwd();
|
|
208
|
+
const result = checkPlan(readFileSync(path, 'utf8'), { ...options, projectRoot });
|
|
142
209
|
if (!result.ok) {
|
|
143
210
|
for (const problem of result.problems) process.stderr.write(`FAIL ${problem}\n`);
|
|
144
211
|
return 1;
|
|
@@ -5,7 +5,7 @@ description: "Make a .pptx slide deck with a consistent design, then render and
|
|
|
5
5
|
|
|
6
6
|
# lit-pptx: a deck compiler with a design direction, a QA gate and a per-slide look
|
|
7
7
|
|
|
8
|
-
This skill turns a request, notes or source files into a finished `.pptx`. It does not draw slides by hand. It chooses a design direction first, writes Markdown slide source, compiles it with the bundled deck engine (native editable charts and KPI rows, Pretendard fonts embedded), gates the result with a mechanical QA script, and then looks at every rendered page. The engine, the
|
|
8
|
+
This skill turns a request, notes or source files into a finished `.pptx`. It does not draw slides by hand. It chooses a design direction first, writes Markdown slide source, compiles it with the bundled deck engine (native editable charts and KPI rows, Pretendard fonts embedded), gates the result with a mechanical QA script, and then looks at every rendered page. The engine, the thirteen tonality packs, the templates, the fonts and the QA scripts all live inside this skill folder; the pinned third-party runtime lives in the shared office runtime of the plugin.
|
|
9
9
|
|
|
10
10
|
## When this applies
|
|
11
11
|
|
|
@@ -31,7 +31,7 @@ Code documentation, bug or test reports and quoted or fenced text stay inert: th
|
|
|
31
31
|
| Mode | Trigger | Completion boundary |
|
|
32
32
|
| --- | --- | --- |
|
|
33
33
|
| lit-default | The activation context says "ask no style questions" (a bare `lit` request, or a headless run) | The direction step chooses the tonality with no questions of any kind and the reply names it and two alternatives; a complete `.pptx` plus the Markdown source even when facts are missing (see "Missing facts"); gate PASS; pages looked at |
|
|
34
|
-
| style-gate | Explicit invocation without a named tonality or template, and the user is present | Run the direction step, then one short `request_user_input` round: the chosen tonality with its one-line reason as the first, one-click option, the two alternatives, and "compare them first"; "알아서 / just make it good" means the first option |
|
|
34
|
+
| style-gate | Explicit invocation without a named tonality or template, and the user is present | Run the direction step, then one short `request_user_input` round: the chosen tonality with its one-line reason as the first, one-click option, recommended first, the two alternatives, and "compare them first"; "알아서 / just make it good" means the first option |
|
|
35
35
|
| compare | The user asks to see options, or the brief leaves the look open on purpose | The compare strip: the first three slides under the chosen tonality and both alternatives, rendered and shown; build the rest under the user's pick |
|
|
36
36
|
| guided | A vague or large brief and the user is present | `references/stages/interview.md` → `references/stages/plan.md` → `references/stages/autopilot.md` |
|
|
37
37
|
| autopilot | A clear brief, or the user delegated the details | 정/반/합 (below), then the compile → gate → look loop |
|
|
@@ -82,7 +82,7 @@ renders/ page PNGs from the look step
|
|
|
82
82
|
```
|
|
83
83
|
Inside Muse the sandbox network is proxy-only, so a failed first-use install (offline, no Python 3.10 to 3.14, no `node`) is `BLOCKED:`. Quote the error line and give the user the pre-warm command to run in a terminal outside Muse: `npx @litfamily/litmuse runtime install office`. Never `pip install` or `npm install -g` anything. `LITMUSE_OFFICE_PYTHON` names a different interpreter; the runtime needs 3.10 to 3.14 and otherwise picks the newest `python3.X` in that range.
|
|
84
84
|
|
|
85
|
-
2. **Choose the direction first: the direction card.** Before any slide is written, decide how the deck should look and write that decision down. A look is a tonality: a pack of palette roles, faces, type ramp, title treatments, layout families, decoration and density that the engine reads as data.
|
|
85
|
+
2. **Choose the direction first: the direction card.** Before any slide is written, decide how the deck should look and write that decision down. A look is a tonality: a pack of palette roles, faces, type ramp, title treatments, layout families, decoration and density that the engine reads as data. Thirteen ship with the skill, and the engine has no default: a deck compiles only under a tonality or a template that someone chose. Follow `references/direction-step.md`:
|
|
86
86
|
- Close the brief: deck type, reader, delivery (presented or read), language. Infer what the brief leaves out and write the inference on the card.
|
|
87
87
|
- Draft the outline (step 3) far enough to count it, then rank the candidates. The deck type gives two or three; the content signals reorder them:
|
|
88
88
|
|
|
@@ -122,8 +122,13 @@ renders/ page PNGs from the look step
|
|
|
122
122
|
| `gazette` | Korean briefing pages: header band, boxed summary, 개조식 evidence at reading size | `references/tonalities/gazette.md` |
|
|
123
123
|
| `studio` | editorial grid, asymmetric splits, side titles, real part numbers | `references/tonalities/studio.md` |
|
|
124
124
|
| `night` | dark ground and light type for data and technical keynotes | `references/tonalities/night.md` |
|
|
125
|
+
| `bauhaus` | primary colours and elementary geometry on display slides, for design and culture talks | `references/tonalities/bauhaus.md` |
|
|
126
|
+
| `computational-brutalism` | retro computing with the grid showing: mono Latin type, ruled tables, a terminal field | `references/tonalities/computational-brutalism.md` |
|
|
127
|
+
| `neo-brutalism` | loud pitch fills: black borders, hard offset shadows, yellow cards, pink accent | `references/tonalities/neo-brutalism.md` |
|
|
128
|
+
| `newsroom` | data journalism for a general reader: masthead titles, grey charts, one orange series | `references/tonalities/newsroom.md` |
|
|
129
|
+
| `riso` | two spot inks on warm paper for community, culture and education programmes | `references/tonalities/riso.md` |
|
|
125
130
|
|
|
126
|
-
`node scripts/compile-deck.js --list-tonalities` prints the
|
|
131
|
+
`node scripts/compile-deck.js --list-tonalities` prints the thirteen and the legacy templates; `--list-layouts <tonality>` prints the pack's families with the title treatments each allows, and its cover, section and closing variants.
|
|
127
132
|
|
|
128
133
|
3. **Outline before prose.** One message per slide. The slide title is a specific topic label that names the subject, the measure and the period ("분기별 방문·대출 추이"; not a sentence such as "방문은 늘었고 대출은 제자리다", and not a bare "현황"); the message itself is the first line of the body. Cover titles are the topic or product name, never a slogan. Typical shape: cover · where things stand · evidence · options compared · recommendation · next steps · closing; each deck type has its own sequence in `references/direction-step.md`. Aim for the fewest slides that carry the argument; split a slide that needs more than four groups or about eight lines. Name one layout family per slide from the chosen pack, by the slide's job (`references/layout-families.md`), never by what the previous slide used. Rule of thumb for a presented deck: one content slide per one to two minutes of talk.
|
|
129
134
|
|
|
@@ -179,7 +184,13 @@ renders/ page PNGs from the look step
|
|
|
179
184
|
- package integrity;
|
|
180
185
|
- the deck-craft checks (`scripts/deck_craft.py`): a content slide whose content fills less than 45% of the area under its title, a deck that is mostly tables with no chart, a shape running off the canvas, an empty outlined box, an unfilled `[blank]`, and a long foreign-language source line on a Korean deck.
|
|
181
186
|
|
|
182
|
-
The craft-floor checks (`scripts/craft_extras.py`)
|
|
187
|
+
The craft-floor checks (`scripts/craft_extras.py`) cover each slide (OF-101 to OF-109): the accent family count (a pack holds its own `qa:` allowance; four families pass everywhere), body line length (90 Latin characters, 38 Korean), right-aligned numeric columns, concentric nested frames, card spacing, flat fills, and empty bands over 35% of a slide or card.
|
|
188
|
+
|
|
189
|
+
Over the whole deck (OF-110 to OF-113), read from the compiled file: three or more title treatments on a deck of eight or more slides, each title drawn as the treatment it names; content slides sharing one composition (title zone × body partition × dominant content) on at most 40% of them; a median empty band under the body of at most 0.20; one shared title frame for content titles and one for display titles.
|
|
190
|
+
|
|
191
|
+
Then OF-114 titles and the cover subtitle written as labels, not sentences; OF-115 with no region left empty — a takeaway column as long as the visual beside it, a title panel as tall as its text, a plate under an empty page; OF-117 with figure cards on matching grounds; OF-118 with a separator between a bold run-in label and its sentence (the engine sets the colon); OF-119 with agenda titles free of count numerals; OF-120 with hard offset shadows only where the pack allows them. With two tonalities of one source, `--sibling other.pptx` adds OF-116: both place titles and bodies alike on the shared grid.
|
|
192
|
+
|
|
193
|
+
On a legacy template the variety checks and the median band are advisories. A MEDIUM finding is reported as advisory. Every failure reason carries a fix hint. Fix the Markdown, never the gate: change the family or the visual (step 4), add the takeaway the slide lacks, merge or split slides, shorten text.
|
|
183
194
|
|
|
184
195
|
8. **Look at the pages.** Render with `python3 "$LITMUSE_LIB/render_pages.py" deck.pptx --out-dir renders --pages 99` (it needs `soffice`; PyMuPDF rasterises the PDF, so `pdftoppm` is not required), then open the PNGs with `read_file`. Read every slide at its real size: hierarchy, Korean glyphs, numbers against the source, anything the gate cannot see (a cramped card, an empty half-slide, a title that wraps into a widow, a title treatment that does not suit the slide's job). Check the deck against its direction card: if the card's "wrong if" line turned out true, rebuild under the alternative and update the card and the reply. Fix and recompile until the gate passes and the pages read well. This compile → gate → look loop is the 정/반/합 below in miniature (the gate and your look are the 반). Three full rounds is the budget; a defect that survives them is reported as a limitation with its slide number. When `soffice` is missing, the render step reports `BLOCKED: slide render check`; the deck is delivered as unverified visually and the reply says so (mode `renderer-missing`). Give the user the install command to run outside Muse (`brew install --cask libreoffice`, or `sudo apt install libreoffice-impress`).
|
|
185
196
|
|
|
@@ -188,7 +199,7 @@ renders/ page PNGs from the look step
|
|
|
188
199
|
The whole loop, by absolute path:
|
|
189
200
|
|
|
190
201
|
```bash
|
|
191
|
-
node "$SKILL_ROOT/scripts/compile-deck.js" --list-tonalities #
|
|
202
|
+
node "$SKILL_ROOT/scripts/compile-deck.js" --list-tonalities # thirteen tonalities and the legacy templates
|
|
192
203
|
node "$SKILL_ROOT/scripts/compile-deck.js" --list-layouts ledger # families, allowed titles, variants of one pack
|
|
193
204
|
node "$SKILL_ROOT/scripts/compile-deck.js" --list-templates # legacy and learned templates
|
|
194
205
|
python3 "$LITMUSE_LIB/office_data.py" check deck.md # when the frontmatter names data:
|
|
@@ -222,7 +233,7 @@ The full checklist is `references/anti-slop-checklist.md`; each tonality's token
|
|
|
222
233
|
|
|
223
234
|
- **Direction.** One tonality per deck, chosen for the audience and the content and recorded on the card. Title treatments follow slide roles (three to five per deck, each in one fixed frame); layout families follow slide jobs; the pack's decoration list is the only decoration.
|
|
224
235
|
- **Hierarchy and fill.** Exactly one primary element per slide, at least twice the size of the next level; two or three secondary; the rest muted. At most four items per group. Density follows the dial, evenly across the deck, and content slides use their body down toward the floor.
|
|
225
|
-
- **Type.** Primary reading text at 12 pt or more (13 pt on the compact step every pack starts from), table cells and captions at 11 pt or more, sources at 9 pt or more with passing contrast. One size ramp (presented, reading or compact, set by the pack and the density dial), no near-equal sizes (14/15/16); display sizes
|
|
236
|
+
- **Type.** Primary reading text at 12 pt or more (13 pt on the compact step every pack starts from), table cells and captions at 11 pt or more, sources at 9 pt or more with passing contrast. One size ramp (presented, reading or compact, set by the pack and the density dial), no near-equal sizes (14/15/16); display sizes on cover, section and statement titles, and the hero step on cover and statement titles in hero packs; every figure at title size at most, inside a structure that gives its label, unit, basis and source. Pretendard Regular and Bold by default; the A2Z faces only when the user or the source asks (`faces: a2z`). Weight builds hierarchy; at most four weights. Korean body line spacing at the loose end (1.3 to 1.45). No one-word widow on a title's last line.
|
|
226
237
|
- **Colour.** Every colour comes from the pack's roles. Tinted neutrals carry most of the surface, one accent of about 10% or less marks the single emphasised item. One colour, one meaning, across the deck. No per-slide one-off hex.
|
|
227
238
|
- **Contrast floors.** Body and captions 4.5:1 on their actual fill, large text and structural lines 3:1. Push toward ink when close; no grey text on a coloured fill.
|
|
228
239
|
- **Anti-slop bans.** No side-stripe accent bars, no border plus heavy shadow on one card, no card inside a card, no eyebrow or 01·02·03 ordinal on every slide, no identical icon-card grids as filler, no cream or beige reading ground, no hand-drawn decoration, no generic titles ("개요", "Overview"), no declarative titles or subtitles, no single exaggerated number as a slide, no padding bullets that restate the title, no placeholder or AI-tell wording.
|
|
@@ -233,11 +244,11 @@ The full checklist is `references/anti-slop-checklist.md`; each tonality's token
|
|
|
233
244
|
| Need | Read |
|
|
234
245
|
| --- | --- |
|
|
235
246
|
| Choosing the direction, the card, the compare strip | `references/direction-step.md` |
|
|
236
|
-
| One tonality's tokens, treatments, families, do and avoid, two worked slides | `references/tonalities/<id>.md` (ledger, signal, atlas, chalk, paper, gazette, studio, night) |
|
|
247
|
+
| One tonality's tokens, treatments, families, do and avoid, two worked slides | `references/tonalities/<id>.md` (ledger, signal, atlas, chalk, paper, gazette, studio, night, bauhaus, computational-brutalism, neo-brutalism, newsroom, riso) |
|
|
237
248
|
| Where titles sit and how the engine picks them | `references/title-treatments.md` |
|
|
238
249
|
| Which family does which job, covers, sections and closings | `references/layout-families.md` |
|
|
239
250
|
| The density and variance dials, fill policies, writing source that fills | `references/density-and-fill.md` |
|
|
240
|
-
| Complete decks that compile and pass the gate | `references/examples/` (
|
|
251
|
+
| Complete decks that compile and pass the gate | `references/examples/` (seventeen, all thirteen tonalities and deck types) |
|
|
241
252
|
| Authoring the Markdown dialect | `references/authoring-guide.md`, `specs/markdown-slide-spec-v1.md`, `specs/markdown-slide-spec-v2.md` |
|
|
242
253
|
| AST shape for debugging a compile error | `specs/slide-ast-v1.schema.json`, `specs/slide-ast-v2.schema.json` |
|
|
243
254
|
| The pack files the engine reads | `templates/tonalities/<id>/pack.yaml` |
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
Copyright 2020 The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono)
|
|
2
|
+
|
|
3
|
+
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
|
4
|
+
This license is copied below, and is also available with a FAQ at:
|
|
5
|
+
https://scripts.sil.org/OFL
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
-----------------------------------------------------------
|
|
9
|
+
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
|
10
|
+
-----------------------------------------------------------
|
|
11
|
+
|
|
12
|
+
PREAMBLE
|
|
13
|
+
The goals of the Open Font License (OFL) are to stimulate worldwide
|
|
14
|
+
development of collaborative font projects, to support the font creation
|
|
15
|
+
efforts of academic and linguistic communities, and to provide a free and
|
|
16
|
+
open framework in which fonts may be shared and improved in partnership
|
|
17
|
+
with others.
|
|
18
|
+
|
|
19
|
+
The OFL allows the licensed fonts to be used, studied, modified and
|
|
20
|
+
redistributed freely as long as they are not sold by themselves. The
|
|
21
|
+
fonts, including any derivative works, can be bundled, embedded,
|
|
22
|
+
redistributed and/or sold with any software provided that any reserved
|
|
23
|
+
names are not used by derivative works. The fonts and derivatives,
|
|
24
|
+
however, cannot be released under any other type of license. The
|
|
25
|
+
requirement for fonts to remain under this license does not apply
|
|
26
|
+
to any document created using the fonts or their derivatives.
|
|
27
|
+
|
|
28
|
+
DEFINITIONS
|
|
29
|
+
"Font Software" refers to the set of files released by the Copyright
|
|
30
|
+
Holder(s) under this license and clearly marked as such. This may
|
|
31
|
+
include source files, build scripts and documentation.
|
|
32
|
+
|
|
33
|
+
"Reserved Font Name" refers to any names specified as such after the
|
|
34
|
+
copyright statement(s).
|
|
35
|
+
|
|
36
|
+
"Original Version" refers to the collection of Font Software components as
|
|
37
|
+
distributed by the Copyright Holder(s).
|
|
38
|
+
|
|
39
|
+
"Modified Version" refers to any derivative made by adding to, deleting,
|
|
40
|
+
or substituting -- in part or in whole -- any of the components of the
|
|
41
|
+
Original Version, by changing formats or by porting the Font Software to a
|
|
42
|
+
new environment.
|
|
43
|
+
|
|
44
|
+
"Author" refers to any designer, engineer, programmer, technical
|
|
45
|
+
writer or other person who contributed to the Font Software.
|
|
46
|
+
|
|
47
|
+
PERMISSION & CONDITIONS
|
|
48
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
49
|
+
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
|
50
|
+
redistribute, and sell modified and unmodified copies of the Font
|
|
51
|
+
Software, subject to the following conditions:
|
|
52
|
+
|
|
53
|
+
1) Neither the Font Software nor any of its individual components,
|
|
54
|
+
in Original or Modified Versions, may be sold by itself.
|
|
55
|
+
|
|
56
|
+
2) Original or Modified Versions of the Font Software may be bundled,
|
|
57
|
+
redistributed and/or sold with any software, provided that each copy
|
|
58
|
+
contains the above copyright notice and this license. These can be
|
|
59
|
+
included either as stand-alone text files, human-readable headers or
|
|
60
|
+
in the appropriate machine-readable metadata fields within text or
|
|
61
|
+
binary files as long as those fields can be easily viewed by the user.
|
|
62
|
+
|
|
63
|
+
3) No Modified Version of the Font Software may use the Reserved Font
|
|
64
|
+
Name(s) unless explicit written permission is granted by the corresponding
|
|
65
|
+
Copyright Holder. This restriction only applies to the primary font name as
|
|
66
|
+
presented to the users.
|
|
67
|
+
|
|
68
|
+
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
|
69
|
+
Software shall not be used to promote, endorse or advertise any
|
|
70
|
+
Modified Version, except to acknowledge the contribution(s) of the
|
|
71
|
+
Copyright Holder(s) and the Author(s) or with their explicit written
|
|
72
|
+
permission.
|
|
73
|
+
|
|
74
|
+
5) The Font Software, modified or unmodified, in part or in whole,
|
|
75
|
+
must be distributed entirely under this license, and must not be
|
|
76
|
+
distributed under any other license. The requirement for fonts to
|
|
77
|
+
remain under this license does not apply to any document created
|
|
78
|
+
using the Font Software.
|
|
79
|
+
|
|
80
|
+
TERMINATION
|
|
81
|
+
This license becomes null and void if any of the above conditions are
|
|
82
|
+
not met.
|
|
83
|
+
|
|
84
|
+
DISCLAIMER
|
|
85
|
+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
86
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
|
87
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
|
88
|
+
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
|
89
|
+
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
90
|
+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
|
91
|
+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
92
|
+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
|
93
|
+
OTHER DEALINGS IN THE FONT SOFTWARE.
|
|
@@ -74,5 +74,36 @@
|
|
|
74
74
|
}
|
|
75
75
|
]
|
|
76
76
|
},
|
|
77
|
-
"
|
|
77
|
+
"jetbrains-mono": {
|
|
78
|
+
"family": "JetBrains Mono",
|
|
79
|
+
"release": "v2.304",
|
|
80
|
+
"repository": "https://github.com/JetBrains/JetBrainsMono",
|
|
81
|
+
"releaseAsset": "https://github.com/JetBrains/JetBrainsMono/releases/download/v2.304/JetBrainsMono-2.304.zip",
|
|
82
|
+
"releaseArchiveSha256": "6f6376c6ed2960ea8a963cd7387ec9d76e3f629125bc33d1fdcd7eb7012f7bbf",
|
|
83
|
+
"license": "SIL Open Font License 1.1 (no Reserved Font Name; files ship unmodified)",
|
|
84
|
+
"sourcePaths": [
|
|
85
|
+
"fonts/ttf/JetBrainsMono-Regular.ttf",
|
|
86
|
+
"fonts/ttf/JetBrainsMono-Bold.ttf",
|
|
87
|
+
"OFL.txt"
|
|
88
|
+
],
|
|
89
|
+
"weightsUsed": "Regular 400 and Bold 700: Latin-only faces of the Computational Brutalism tonality; Hangul in their runs is set in Pretendard",
|
|
90
|
+
"files": [
|
|
91
|
+
{
|
|
92
|
+
"file": "jetbrains-mono/JetBrainsMono-Regular.ttf",
|
|
93
|
+
"bytes": 273900,
|
|
94
|
+
"sha256": "a0bf60ef0f83c5ed4d7a75d45838548b1f6873372dfac88f71804491898d138f"
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"file": "jetbrains-mono/JetBrainsMono-Bold.ttf",
|
|
98
|
+
"bytes": 277828,
|
|
99
|
+
"sha256": "5590990c82e097397517f275f430af4546e1c45cff408bde4255dad142479dcb"
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"file": "jetbrains-mono/OFL.txt",
|
|
103
|
+
"bytes": 4399,
|
|
104
|
+
"sha256": "30f0c136e3c88e422d0791acd97238870f9054a9729bc34cf2ff0d4ed8cac4ad"
|
|
105
|
+
}
|
|
106
|
+
]
|
|
107
|
+
},
|
|
108
|
+
"totalBytes": 5802755
|
|
78
109
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Every deck starts by choosing how it should look, before a single slide is written. The choice is
|
|
4
4
|
a tonality: a pack of colours, type sizes, title treatments, layout families and density that the
|
|
5
|
-
engine reads as data.
|
|
5
|
+
engine reads as data. Thirteen tonalities ship with the skill, and four legacy templates remain for
|
|
6
6
|
users who name them. Without this step the engine would have nothing to draw with, and the skill
|
|
7
7
|
would drift back to one look for every topic, which is the failure this whole design exists to end.
|
|
8
8
|
|
|
@@ -16,7 +16,7 @@ card in the build log. It asks the user nothing unless the brief leaves the look
|
|
|
16
16
|
Name four facts before ranking anything. When the brief does not say them, infer them from the
|
|
17
17
|
request and the sources, and write the inference on the card so the user can correct it.
|
|
18
18
|
|
|
19
|
-
- **Deck type.** One of the
|
|
19
|
+
- **Deck type.** One of the thirteen below, or "other, nearest to …".
|
|
20
20
|
- **Reader.** Who sees it, where, and for how long: a board reading at a desk, a hall watching a
|
|
21
21
|
stage screen, a class that will review the file later.
|
|
22
22
|
- **Delivery.** Presented live, sent ahead and read alone, or both.
|
|
@@ -37,6 +37,11 @@ start from. The first one is the default when nothing else moves the order.
|
|
|
37
37
|
| Image-led (product, site, portfolio) | Atlas (10, 7); Studio (10, 8); Signal (10, 6) for a launch |
|
|
38
38
|
| Korean text briefing (보고서형 덱) | Gazette (10, 4); Ledger (10, 5) |
|
|
39
39
|
| Status update (주간·월간 보고) | Ledger (10, 5); Gazette (10, 4); Night (10, 6) |
|
|
40
|
+
| Launch, demo day or campaign (런칭·데모데이·캠페인) | Neo-Brutalism (10, 7); Signal (10, 6); Studio (10, 7) |
|
|
41
|
+
| Engineering or developer review (아키텍처·인프라·장애 리뷰) | Computational Brutalism (10, 7); Night (10, 6) for a stage; Ledger (10, 5) when it is read alone |
|
|
42
|
+
| Design or culture lecture (디자인·건축·전시·워크숍) | Bauhaus (10, 7); Studio (10, 8); Atlas (10, 7) when the works are the deck |
|
|
43
|
+
| Community, culture or education programme (커뮤니티·문화·교육 프로그램) | Riso (10, 7); Studio (10, 7); Bauhaus (10, 7) for a design programme |
|
|
44
|
+
| Data story for the public (주민·독자 대상 데이터 브리핑) | Newsroom (10, 6); Gazette (10, 4) when it is read alone; Ledger (10, 5) |
|
|
40
45
|
|
|
41
46
|
## 3. Measure the source and reorder
|
|
42
47
|
|
|
@@ -58,6 +63,13 @@ the deck-type order, so the same source always gives the same choice.
|
|
|
58
63
|
| Equations, definitions, or a how-it-works sequence of three or more steps | present | Chalk or Paper up one place |
|
|
59
64
|
| A dark room (keynote, stage, demo day) | stated in the brief | Night up one place |
|
|
60
65
|
| A pack would leave a slide role with no family or title it allows | any slide | drop that pack |
|
|
66
|
+
| The brief names a style rather than a pack id | 네오 브루탈리즘, neo-brutalism, neo-brutalist; 컴퓨테이셔널 브루탈리즘, computational brutalism, 레트로 퓨처, retro-futurist, terminal look; 바우하우스, Bauhaus; 리소, risograph, zine; 뉴스룸, data journalism, explainer | that pack, as if named; a bare 브루탈리즘 or brutalist takes Neo-Brutalism for a pitch or launch and Computational Brutalism for a technical deck, and the card says which reading it took |
|
|
67
|
+
| Metrics with units, version numbers or identifiers (p99, rps, v3, endpoint names) | on a third of the content slides | Computational Brutalism up one place |
|
|
68
|
+
| A young or consumer audience, a sign-up or launch ask | stated in the brief | Neo-Brutalism up one place |
|
|
69
|
+
| Works, makers, periods or schools as the subject | on a third of the content slides | Bauhaus up one place |
|
|
70
|
+
| Participants, sessions, dates and places for a community or a class | on a third of the content slides | Riso up one place |
|
|
71
|
+
| Charts with one point each, for readers outside the field (residents, members, the press) | stated in the brief | Newsroom up one place |
|
|
72
|
+
| A board, investor committee, finance or public-sector reader, or a sensitive topic (loss, safety, HR) | stated in the brief | Neo-Brutalism, Computational Brutalism, Bauhaus and Riso drop out |
|
|
61
73
|
|
|
62
74
|
The last row matters more than it looks. Atlas, Ledger and Gazette have no statement title, Atlas
|
|
63
75
|
has no table family at all, and Signal has neither a full ledger table nor a dashboard. A pack that cannot carry one
|
|
@@ -180,6 +192,11 @@ the job before writing a new deck.
|
|
|
180
192
|
| `10-status-update-ledger-ko.md` | status update | Ledger | Gazette, Night |
|
|
181
193
|
| `11-portfolio-studio-en.md` | image-led portfolio | Studio | Atlas, Signal |
|
|
182
194
|
| `12-research-tutorial-chalk-en.md` | research tutorial | Chalk | Paper, Night |
|
|
195
|
+
| `13-engineering-review-computational-brutalism-ko.md` | engineering review | Computational Brutalism | Night, Ledger |
|
|
196
|
+
| `14-launch-pitch-neo-brutalism-ko.md` | launch pitch | Neo-Brutalism | Signal, Studio |
|
|
197
|
+
| `15-design-lecture-bauhaus-ko.md` | design lecture | Bauhaus | Studio, Atlas |
|
|
198
|
+
| `16-community-programme-riso-ko.md` | community programme | Riso | Studio, Bauhaus |
|
|
199
|
+
| `17-public-data-briefing-newsroom-ko.md` | data story for residents | Newsroom | Gazette, Ledger |
|
|
183
200
|
|
|
184
201
|
The examples that place pictures name `assets/example-a.png`, `assets/example-b.png` and
|
|
185
202
|
`assets/example-c.png`; supply real images under those names (or change the paths) before
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
---
|
|
2
|
+
tonality: computational-brutalism
|
|
3
|
+
title: API 게이트웨이 v3 전환 리뷰
|
|
4
|
+
date: 2026-10-20
|
|
5
|
+
department: 예시 기업 플랫폼팀
|
|
6
|
+
presenter: 예시 발표자
|
|
7
|
+
notice: 예시 데이터 — 실제 수치로 바꿔 주세요
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
layout: cover-typographic
|
|
12
|
+
|
|
13
|
+
# API 게이트웨이 v3 전환 리뷰
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
layout: kpi-row
|
|
18
|
+
|
|
19
|
+
## v3 전환 4주 운영 지표, 2026년 9-10월
|
|
20
|
+
|
|
21
|
+
| p99 지연 | 처리량 | 오류율 | 노드 수 |
|
|
22
|
+
|---|---|---|---|
|
|
23
|
+
| 182 ms | 41k rps | 0.07% | 24 |
|
|
24
|
+
| v2 410 ms | v2 18k rps | v2 0.31% | v2 40 |
|
|
25
|
+
|
|
26
|
+
> 운영 클러스터 4주 평균, 2026년 9월 22일-10월 19일 (예시)
|
|
27
|
+
|
|
28
|
+
- p99 지연은 절반 아래로 줄었고, 같은 트래픽을 노드 24대가 처리한다
|
|
29
|
+
- 오류율 0.07%는 SLO 0.1% 안쪽이고, 월 비용은 2,100만 원 줄었다
|
|
30
|
+
- 출처: 예시 관측 대시보드, 2026년 10월 (예시)
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
layout: chart-insight
|
|
35
|
+
|
|
36
|
+
## 주간 p99 지연 추이, v2와 v3
|
|
37
|
+
|
|
38
|
+
::: chart type=line unit="ms"
|
|
39
|
+
| 주 | v2 p99 (ms) | v3 p99 (ms) |
|
|
40
|
+
|---|---|---|
|
|
41
|
+
| 8월 4주 | 402 | 236 |
|
|
42
|
+
| 9월 1주 | 415 | 221 |
|
|
43
|
+
| 9월 2주 | 408 | 204 |
|
|
44
|
+
| 9월 3주 | 421 | 193 |
|
|
45
|
+
| 9월 4주 | 410 | 188 |
|
|
46
|
+
| 10월 1주 | 412 | 184 |
|
|
47
|
+
| 10월 2주 | 406 | 182 |
|
|
48
|
+
> 주간 p99 지연, 같은 트래픽 미러링 기준 (예시 데이터)
|
|
49
|
+
:::
|
|
50
|
+
|
|
51
|
+
- v3는 7주 동안 236 ms에서 182 ms로 내려왔고, v2는 400 ms대에 머문다
|
|
52
|
+
- 개선의 절반은 커넥션 풀 재사용, 나머지는 직렬화 경로 교체에서 나왔다
|
|
53
|
+
- 출처: 예시 관측 대시보드, 2026년 8-10월 (예시)
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
layout: table-insight
|
|
58
|
+
title: bottom-anchor
|
|
59
|
+
|
|
60
|
+
## 엔드포인트별 지연과 오류, 10월 2주
|
|
61
|
+
|
|
62
|
+
| 엔드포인트 | 호출 비중 | p50 (ms) | p99 (ms) | 오류율 | v2 대비 p99 |
|
|
63
|
+
|---|---|---|---|---|---|
|
|
64
|
+
| GET /orders | 38% | 21 | 142 | 0.03% | ▼ −61% |
|
|
65
|
+
| POST /orders | 17% | 48 | 231 | 0.11% | ▼ −52% |
|
|
66
|
+
| GET /tracking | 29% | 18 | 120 | 0.02% | ▼ −64% |
|
|
67
|
+
| POST /auth/token | 9% | 35 | 264 | 0.19% | ▼ −38% |
|
|
68
|
+
| 기타 14개 | 7% | 30 | 198 | 0.08% | ▼ −49% |
|
|
69
|
+
|
|
70
|
+
> 표 1. 엔드포인트별 지연과 오류율, 2026년 10월 2주, 예시 게이트웨이 접근 로그 (예시 데이터)
|
|
71
|
+
|
|
72
|
+
- 토큰 발급만 오류율이 SLO 근처다: 외부 인증 서버 타임아웃이 원인이다
|
|
73
|
+
- 인증 서버 증설 전까지 토큰 캐시 TTL을 5분에서 15분으로 늘린다
|
|
74
|
+
- 호출의 67%를 차지하는 두 조회 경로는 p99가 150 ms 아래다
|
|
75
|
+
- 주문 생성은 재고 서비스 호출 때문에 조회보다 p99가 1.6배 길다
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
layout: method
|
|
80
|
+
|
|
81
|
+
## v3 요청 처리 경로
|
|
82
|
+
|
|
83
|
+

|
|
84
|
+
|
|
85
|
+
- **1. 수신** TLS 종료와 요청 파싱, 커넥션 풀에서 업스트림 연결 재사용
|
|
86
|
+
- **2. 인증** 토큰 검증 캐시 우선, 캐시 미스만 인증 서버 호출
|
|
87
|
+
- **3. 라우팅** 경로 규칙 테이블을 메모리에 올려 조회, 규칙 312개
|
|
88
|
+
- **4. 전달** 업스트림 호출과 재시도 1회, 서킷 브레이커 임계 5%
|
|
89
|
+
- **5. 기록** 구조화 로그와 추적 스팬을 비동기로 내보냄
|
|
90
|
+
- 출처: 예시 플랫폼팀 설계 문서 v3.2, 2026년 8월 (예시)
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
layout: comparison
|
|
95
|
+
|
|
96
|
+
## v2와 v3 구성 비교
|
|
97
|
+
|
|
98
|
+
:::: columns 1fr 1fr
|
|
99
|
+
::: col
|
|
100
|
+
- **v2 (2023-2026)**
|
|
101
|
+
(1) 런타임: 요청마다 새 업스트림 연결
|
|
102
|
+
(2) 인증: 매 요청 인증 서버 호출
|
|
103
|
+
(3) 설정: 배포 때마다 규칙 파일 재적재
|
|
104
|
+
(4) 노드: 40대, 피크 CPU 71%
|
|
105
|
+
(5) 배포: 주 2회, 배포당 평균 38분
|
|
106
|
+
:::
|
|
107
|
+
::: col
|
|
108
|
+
- **v3 (2026-)**
|
|
109
|
+
(1) 런타임: 커넥션 풀 재사용, 연결 수립 −92%
|
|
110
|
+
(2) 인증: 검증 캐시 적중률 94%
|
|
111
|
+
(3) 설정: 규칙 핫 리로드, 배포 없이 반영
|
|
112
|
+
(4) 노드: 24대, 피크 CPU 58%
|
|
113
|
+
(5) 배포: 하루 6회, 배포당 평균 7분
|
|
114
|
+
:::
|
|
115
|
+
::::
|
|
116
|
+
|
|
117
|
+
- 출처: 예시 플랫폼팀 부하 시험 보고서, 2026년 9월 (예시)
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
layout: step-diagram
|
|
122
|
+
title: top-rule
|
|
123
|
+
|
|
124
|
+
## 남은 전환 단계와 종료 조건
|
|
125
|
+
|
|
126
|
+
- **1. 섀도** 트래픽 5%를 v3로 복제해 응답을 비교한다
|
|
127
|
+
(1) 종료 조건: 72시간 불일치 0건 · 완료
|
|
128
|
+
- **2. 카나리** 한 리전에서 실트래픽 10%를 v3로 보낸다
|
|
129
|
+
(1) 종료 조건: p99 250 ms 미만, 오류율 0.1% 미만 · 완료
|
|
130
|
+
- **3. 확대** 50%, 100% 순서로 하루에 한 리전씩 넓힌다
|
|
131
|
+
(1) 종료 조건: 7일간 롤백 0건 · 진행 중
|
|
132
|
+
- **4. 폐기** v2를 드레인하고 노드 40대를 반납한다
|
|
133
|
+
(1) 담당: 예시 플랫폼팀, 11월 4주 · 예정
|
|
134
|
+
- 출처: 예시 전환 런북 v1.4, 2026년 10월 (예시)
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
layout: statement
|
|
139
|
+
|
|
140
|
+
## 남은 오류는 어디에서 오는가?
|
|
141
|
+
|
|
142
|
+
토큰 발급 오류의 92%는 v3가 아니라 외부 인증 서버의 2초 타임아웃에서 나온다.
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
layout: closing-decision-box
|
|
147
|
+
title: top-rule
|
|
148
|
+
|
|
149
|
+
## v2 폐기와 인증 서버 증설 승인 안건
|
|
150
|
+
|
|
151
|
+
- 결정할 것: 11월 4주 v2 폐기와 인증 서버 2대 증설을 함께 승인하면 월 2,100만 원을 줄인다
|
|
152
|
+
|
|
153
|
+
| 안건 | 비용 | 결정 시점 | 담당 |
|
|
154
|
+
|---|---|---|---|
|
|
155
|
+
| v2 노드 40대 반납 | −2,100만 원/월 | 11월 2주 | 예시 플랫폼팀 |
|
|
156
|
+
| 인증 서버 2대 증설 | +260만 원/월 | 11월 1주 | 예시 보안팀 |
|
|
157
|
+
| 토큰 캐시 TTL 15분 | 비용 없음 | 즉시 | 예시 플랫폼팀 |
|
|
158
|
+
| v3 운영 런북 이관 | 비용 없음 | 11월 4주 | 예시 SRE팀 |
|
|
159
|
+
|
|
160
|
+
> 표 2. 승인 요청 안건 (예시)
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
layout: references-appendix
|
|
165
|
+
|
|
166
|
+
## 붙임: 지표 정의와 자료 출처
|
|
167
|
+
|
|
168
|
+
- [1] p99 지연: 요청 99%가 이 시간 안에 끝나는 값, 1분 창 집계
|
|
169
|
+
- [2] 처리량: 초당 요청 수(rps), 피크 1시간 평균
|
|
170
|
+
- [3] 오류율: 5xx 응답과 타임아웃을 전체 요청으로 나눈 값
|
|
171
|
+
- [4] 예시 관측 대시보드, 2026년 8-10월 (예시)
|
|
172
|
+
- [5] 예시 플랫폼팀 설계 문서 v3.2와 전환 런북 v1.4 (예시)
|
|
173
|
+
---
|