@ritualai/cli 0.7.16 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/init.js +406 -96
- package/dist/commands/init.js.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/build-flow-explainer.js +226 -0
- package/dist/lib/build-flow-explainer.js.map +1 -0
- package/dist/lib/final-cta-box.js +224 -0
- package/dist/lib/final-cta-box.js.map +1 -0
- package/dist/lib/onboarding-state.js +140 -0
- package/dist/lib/onboarding-state.js.map +1 -0
- package/dist/lib/persona-picker.js +171 -0
- package/dist/lib/persona-picker.js.map +1 -0
- package/dist/lib/persona-samples.js +245 -0
- package/dist/lib/persona-samples.js.map +1 -0
- package/dist/lib/project-config.js.map +1 -1
- package/dist/lib/workspace-explainer.js +193 -0
- package/dist/lib/workspace-explainer.js.map +1 -0
- package/dist/lib/workspace-flow.js +8 -7
- package/dist/lib/workspace-flow.js.map +1 -1
- package/package.json +73 -73
- package/skills/claude-code/ritual/.ritual-bundle.json +2 -2
- package/skills/claude-code/ritual/references/build-flow.md +51 -14
- package/skills/codex/ritual/.ritual-bundle.json +2 -2
- package/skills/codex/ritual/references/build-flow.md +51 -14
- package/skills/cursor/ritual/.ritual-bundle.json +2 -2
- package/skills/cursor/ritual/references/build-flow.md +51 -14
- package/skills/gemini/ritual/.ritual-bundle.json +2 -2
- package/skills/gemini/ritual/references/build-flow.md +51 -14
- package/skills/kiro/ritual/.ritual-bundle.json +2 -2
- package/skills/kiro/ritual/references/build-flow.md +51 -14
- package/skills/vscode/ritual/.ritual-bundle.json +2 -2
- package/skills/vscode/ritual/references/build-flow.md +51 -14
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Per-machine onboarding state.
|
|
4
|
+
*
|
|
5
|
+
* Tracks whether the three FTUE screens (persona picker, workspace
|
|
6
|
+
* explainer, build-flow explainer) have been shown on this machine.
|
|
7
|
+
* We want the explainers to teach the mental model ONCE per machine,
|
|
8
|
+
* not every time someone runs `ritual init` in a new repo — by the
|
|
9
|
+
* time you're cloning your second project we'd just be in your way.
|
|
10
|
+
*
|
|
11
|
+
* Storage shape (`~/.config/ritual/onboarding.json`):
|
|
12
|
+
* {
|
|
13
|
+
* "version": 1,
|
|
14
|
+
* "personaPickedAt": "2026-05-19T20:01:00Z",
|
|
15
|
+
* "personaSlug": "backend-services",
|
|
16
|
+
* "workspaceExplainerSeenAt": "2026-05-19T20:01:12Z",
|
|
17
|
+
* "buildFlowExplainerSeenAt": "2026-05-19T20:01:25Z"
|
|
18
|
+
* }
|
|
19
|
+
*
|
|
20
|
+
* Each field is optional and additive — we only set it once that
|
|
21
|
+
* screen has been shown (and, for the picker, confirmed). Missing
|
|
22
|
+
* fields are treated as "not yet seen". This makes the schema
|
|
23
|
+
* forward-compatible: adding a screen #4 in a later release just
|
|
24
|
+
* means a new field that's missing on existing installs.
|
|
25
|
+
*
|
|
26
|
+
* Why a separate file from `credentials.json`:
|
|
27
|
+
* - We want to be able to reset onboarding (`ritual init
|
|
28
|
+
* --re-onboard`) without nuking the user's auth tokens.
|
|
29
|
+
* - This file is non-secret — losing it just means we re-onboard
|
|
30
|
+
* once, never a security issue. Different blast radius from
|
|
31
|
+
* credentials, so different file.
|
|
32
|
+
*
|
|
33
|
+
* Why per-MACHINE not per-PROJECT:
|
|
34
|
+
* - The persona is a "what kind of work do you do" question, not
|
|
35
|
+
* "what kind of work does this repo support". You're the same
|
|
36
|
+
* dev across all your repos.
|
|
37
|
+
* - The explainers are mental-model teaching — once you've seen
|
|
38
|
+
* them, you've seen them.
|
|
39
|
+
* - Project-level overrides still work via `.ritual/config.json`
|
|
40
|
+
* (the per-project persona override picks up here as fallback
|
|
41
|
+
* when the project file doesn't set one explicitly).
|
|
42
|
+
*/
|
|
43
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
+
exports.readOnboardingState = readOnboardingState;
|
|
45
|
+
exports.updateOnboardingState = updateOnboardingState;
|
|
46
|
+
exports.shouldShowPersonaPicker = shouldShowPersonaPicker;
|
|
47
|
+
exports.shouldShowWorkspaceExplainer = shouldShowWorkspaceExplainer;
|
|
48
|
+
exports.shouldShowBuildFlowExplainer = shouldShowBuildFlowExplainer;
|
|
49
|
+
exports.resetOnboardingState = resetOnboardingState;
|
|
50
|
+
const node_os_1 = require("node:os");
|
|
51
|
+
const node_path_1 = require("node:path");
|
|
52
|
+
const node_fs_1 = require("node:fs");
|
|
53
|
+
/** Bump if the on-disk schema changes incompatibly. */
|
|
54
|
+
const CURRENT_VERSION = 1;
|
|
55
|
+
/**
|
|
56
|
+
* Resolve the onboarding-state file path. Honors `XDG_CONFIG_HOME`
|
|
57
|
+
* for the same reasons as `config.ts` — Linux dotfile convention +
|
|
58
|
+
* clean override seam for tests.
|
|
59
|
+
*
|
|
60
|
+
* Evaluated lazily on each call so tests can mutate env between
|
|
61
|
+
* sub-tests without needing to reset the module cache.
|
|
62
|
+
*/
|
|
63
|
+
function onboardingPath() {
|
|
64
|
+
const xdg = process.env.XDG_CONFIG_HOME;
|
|
65
|
+
const base = xdg && xdg.length > 0 ? xdg : (0, node_path_1.join)((0, node_os_1.homedir)(), '.config');
|
|
66
|
+
return (0, node_path_1.join)(base, 'ritual', 'onboarding.json');
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Read the current state. Returns an empty object (with the right
|
|
70
|
+
* version) when the file doesn't exist or is corrupt — corruption
|
|
71
|
+
* here is a "show the screens again" outcome, never a hard error,
|
|
72
|
+
* because the worst case is we onboard the user a second time.
|
|
73
|
+
*/
|
|
74
|
+
function readOnboardingState() {
|
|
75
|
+
const path = onboardingPath();
|
|
76
|
+
if (!(0, node_fs_1.existsSync)(path))
|
|
77
|
+
return { version: CURRENT_VERSION };
|
|
78
|
+
try {
|
|
79
|
+
const raw = (0, node_fs_1.readFileSync)(path, 'utf-8');
|
|
80
|
+
const parsed = JSON.parse(raw);
|
|
81
|
+
if (parsed.version !== CURRENT_VERSION) {
|
|
82
|
+
// Future schema bumps land here — for now we treat any
|
|
83
|
+
// mismatch as "fresh state" rather than try to migrate.
|
|
84
|
+
return { version: CURRENT_VERSION };
|
|
85
|
+
}
|
|
86
|
+
return { ...parsed, version: CURRENT_VERSION };
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return { version: CURRENT_VERSION };
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Merge `patch` into the existing on-disk state and persist. We
|
|
94
|
+
* always read-then-write rather than blind-overwrite so a partial
|
|
95
|
+
* patch (e.g. "mark workspace explainer seen") doesn't blow away
|
|
96
|
+
* unrelated fields (persona pick) written by an earlier screen.
|
|
97
|
+
*/
|
|
98
|
+
function updateOnboardingState(patch) {
|
|
99
|
+
const current = readOnboardingState();
|
|
100
|
+
const next = { ...current, ...patch, version: CURRENT_VERSION };
|
|
101
|
+
persist(next);
|
|
102
|
+
return next;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Convenience predicates the init flow uses to decide whether to
|
|
106
|
+
* render each screen. Centralized here so the gating policy lives
|
|
107
|
+
* in one place — if we later decide the workspace explainer should
|
|
108
|
+
* re-show after a year or after a major version bump, we change
|
|
109
|
+
* the predicate, not every call site.
|
|
110
|
+
*/
|
|
111
|
+
function shouldShowPersonaPicker(state) {
|
|
112
|
+
return !state.personaPickedAt;
|
|
113
|
+
}
|
|
114
|
+
function shouldShowWorkspaceExplainer(state) {
|
|
115
|
+
return !state.workspaceExplainerSeenAt;
|
|
116
|
+
}
|
|
117
|
+
function shouldShowBuildFlowExplainer(state) {
|
|
118
|
+
return !state.buildFlowExplainerSeenAt;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Wipe the on-disk state. Used by `ritual init --re-onboard` (a
|
|
122
|
+
* support escape hatch for "I want to see the intro again"). We
|
|
123
|
+
* write `{}` instead of unlinking so file permissions / SELinux
|
|
124
|
+
* contexts / Windows ACLs aren't disturbed.
|
|
125
|
+
*/
|
|
126
|
+
function resetOnboardingState() {
|
|
127
|
+
persist({ version: CURRENT_VERSION });
|
|
128
|
+
}
|
|
129
|
+
// ─── internal ──────────────────────────────────────────────────────────────
|
|
130
|
+
function persist(state) {
|
|
131
|
+
const path = onboardingPath();
|
|
132
|
+
const dir = (0, node_path_1.join)(path, '..');
|
|
133
|
+
if (!(0, node_fs_1.existsSync)(dir))
|
|
134
|
+
(0, node_fs_1.mkdirSync)(dir, { recursive: true });
|
|
135
|
+
// 0600 on the file so we don't widen access just because the
|
|
136
|
+
// parent dir is group-readable. Onboarding state isn't secret
|
|
137
|
+
// but there's no reason to make it world-visible either.
|
|
138
|
+
(0, node_fs_1.writeFileSync)(path, JSON.stringify(state, null, 2), { encoding: 'utf-8', mode: 0o600 });
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=onboarding-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"onboarding-state.js","sourceRoot":"","sources":["../../src/lib/onboarding-state.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Persona picker — onboarding screen #1 of 3.
|
|
4
|
+
*
|
|
5
|
+
* Shown once per machine on first `ritual init` (gated by
|
|
6
|
+
* onboarding-state.ts). Determines two downstream things:
|
|
7
|
+
*
|
|
8
|
+
* 1. The default template `/ritual build` will reach for. Persona
|
|
9
|
+
* slug equals the template's schema.id, so a user who picks
|
|
10
|
+
* "Backend Services" gets the backend-services Engineering
|
|
11
|
+
* template by default — they can still override per build.
|
|
12
|
+
* 2. The accent + framing used in screens #2 and #3 so the whole
|
|
13
|
+
* onboarding cohort feels personal.
|
|
14
|
+
*
|
|
15
|
+
* UI version (this file): numbered-list with color accents, chip
|
|
16
|
+
* tags ("APIs · workers · idempotency"), and a "see more" gate so
|
|
17
|
+
* we surface the 5 most-common personas first and the long tail
|
|
18
|
+
* only when asked. This is the pragmatic version; an Ink-based
|
|
19
|
+
* card UI is a polish pass we can layer on later without changing
|
|
20
|
+
* the contract here.
|
|
21
|
+
*
|
|
22
|
+
* Non-TTY fallback: returns `null` immediately. Callers must check
|
|
23
|
+
* `process.stdin.isTTY` before invoking the interactive version —
|
|
24
|
+
* see init.ts for the pattern. The seed value can also be supplied
|
|
25
|
+
* via `--persona <slug>` on the command line for CI bootstrapping.
|
|
26
|
+
*/
|
|
27
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
28
|
+
exports.__test = void 0;
|
|
29
|
+
exports.pickPersona = pickPersona;
|
|
30
|
+
const colors_1 = require("./colors");
|
|
31
|
+
const prompt_1 = require("./prompt");
|
|
32
|
+
const persona_samples_1 = require("./persona-samples");
|
|
33
|
+
/**
|
|
34
|
+
* Run the persona picker. Returns the picked persona, or `null` if
|
|
35
|
+
* the user skipped explicitly (entered empty / "skip" / etc).
|
|
36
|
+
*
|
|
37
|
+
* Throws on non-TTY stdin (Node's readline doesn't support it). The
|
|
38
|
+
* caller must gate on `process.stdin.isTTY` first.
|
|
39
|
+
*/
|
|
40
|
+
async function pickPersona(opts = {}) {
|
|
41
|
+
const featured = orderByFeatured(persona_samples_1.PERSONA_SAMPLES, persona_samples_1.FEATURED_PERSONA_SLUGS);
|
|
42
|
+
let showingAll = opts.showAll ?? false;
|
|
43
|
+
let visibleCount = showingAll ? featured.length : Math.min(persona_samples_1.FEATURED_PERSONA_SLUGS.length, featured.length);
|
|
44
|
+
printHeader();
|
|
45
|
+
printPersonaList(featured.slice(0, visibleCount));
|
|
46
|
+
// Initial prompt: number, "more", or skip
|
|
47
|
+
while (true) {
|
|
48
|
+
const answer = (await (0, prompt_1.prompt)(formatPickPrompt(visibleCount, showingAll))).trim();
|
|
49
|
+
if (!answer || answer.toLowerCase() === 'skip') {
|
|
50
|
+
process.stdout.write('\n' + (0, colors_1.dim)(' no persona set — /ritual build will ask you per exploration.') + '\n\n');
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
// Allow "more" to expand the list (one-way; once expanded, the
|
|
54
|
+
// long-tail personas are shown until pick / skip).
|
|
55
|
+
if (answer.toLowerCase() === 'more' && !showingAll) {
|
|
56
|
+
const tail = featured.slice(visibleCount);
|
|
57
|
+
process.stdout.write('\n');
|
|
58
|
+
printPersonaList(tail, visibleCount);
|
|
59
|
+
showingAll = true;
|
|
60
|
+
visibleCount = featured.length;
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
const idx = parseChoice(answer, featured.length);
|
|
64
|
+
if (idx === null) {
|
|
65
|
+
process.stdout.write((0, colors_1.dim)(` didn't recognize "${answer}" — try a number, "more", or "skip".`) + '\n');
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
const picked = featured[idx];
|
|
69
|
+
process.stdout.write('\n ' +
|
|
70
|
+
(0, colors_1.boldColor)(picked.accent, `✓ ${picked.label}`) +
|
|
71
|
+
(0, colors_1.dim)(` · default template for /ritual build`) +
|
|
72
|
+
'\n\n');
|
|
73
|
+
return { slug: picked.slug, label: picked.label };
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// ─── rendering ──────────────────────────────────────────────────────────────
|
|
77
|
+
function printHeader() {
|
|
78
|
+
const lines = [
|
|
79
|
+
'',
|
|
80
|
+
' ' + (0, colors_1.boldColor)(colors_1.RITUAL_TEAL, 'What kind of code do you work on most?'),
|
|
81
|
+
' ' + (0, colors_1.dim)('you can always change this later — it\'s a default, not a lock-in.'),
|
|
82
|
+
'',
|
|
83
|
+
];
|
|
84
|
+
for (const l of lines)
|
|
85
|
+
process.stdout.write(l + '\n');
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Render a list of personas as `N) Label tag · tag · tag`.
|
|
89
|
+
*
|
|
90
|
+
* `startIndex` is the 0-based index of the FIRST persona in the slice,
|
|
91
|
+
* so when we render the long-tail after "more", the numbering continues
|
|
92
|
+
* from where the featured list left off (6, 7, 8…).
|
|
93
|
+
*/
|
|
94
|
+
function printPersonaList(personas, startIndex = 0) {
|
|
95
|
+
const numWidth = String(startIndex + personas.length).length;
|
|
96
|
+
const labelWidth = Math.max(...personas.map((p) => p.label.length));
|
|
97
|
+
for (let i = 0; i < personas.length; i++) {
|
|
98
|
+
const p = personas[i];
|
|
99
|
+
const n = String(startIndex + i + 1).padStart(numWidth, ' ');
|
|
100
|
+
const label = (0, colors_1.boldColor)(p.accent, p.label.padEnd(labelWidth, ' '));
|
|
101
|
+
const tags = p.caresAbout.slice(0, 4).join(' · ');
|
|
102
|
+
process.stdout.write(` ${(0, colors_1.color)(p.accent, n + ')')} ${label} ${(0, colors_1.dim)(tags)}\n`);
|
|
103
|
+
}
|
|
104
|
+
process.stdout.write('\n');
|
|
105
|
+
}
|
|
106
|
+
function formatPickPrompt(visibleCount, showingAll) {
|
|
107
|
+
const hint = showingAll
|
|
108
|
+
? `pick a number (1-${visibleCount}), or "skip"`
|
|
109
|
+
: `pick a number (1-${visibleCount}), "more" to see the rest, or "skip"`;
|
|
110
|
+
return ` ${(0, colors_1.dim)(hint)}\n ${(0, colors_1.color)(colors_1.RITUAL_TEAL, '›')} `;
|
|
111
|
+
}
|
|
112
|
+
// ─── helpers ────────────────────────────────────────────────────────────────
|
|
113
|
+
/**
|
|
114
|
+
* Reorder `samples` so the featured slugs come first (in the order
|
|
115
|
+
* given by `featuredSlugs`) and the rest follow in their natural
|
|
116
|
+
* order. Defensive against missing slugs — if a featured slug has no
|
|
117
|
+
* matching sample, we just skip it.
|
|
118
|
+
*/
|
|
119
|
+
function orderByFeatured(samples, featuredSlugs) {
|
|
120
|
+
const bySlug = new Map(samples.map((s) => [s.slug, s]));
|
|
121
|
+
const featured = [];
|
|
122
|
+
for (const slug of featuredSlugs) {
|
|
123
|
+
const s = bySlug.get(slug);
|
|
124
|
+
if (s)
|
|
125
|
+
featured.push(s);
|
|
126
|
+
}
|
|
127
|
+
const tail = samples.filter((s) => !featuredSlugs.includes(s.slug));
|
|
128
|
+
return [...featured, ...tail];
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Parse a user's text answer into a 0-based index into the full
|
|
132
|
+
* persona list. Returns null if the answer doesn't resolve. We
|
|
133
|
+
* accept 1-based numbers (matching the rendered list) and a tiny
|
|
134
|
+
* set of label aliases — "backend", "frontend" — for hand-typers.
|
|
135
|
+
*
|
|
136
|
+
* Exported (alongside `orderByFeatured`) under `__test` so the spec
|
|
137
|
+
* can exercise parsing without spinning up readline. Not part of the
|
|
138
|
+
* public API; treat the underscore prefix as the contract.
|
|
139
|
+
*/
|
|
140
|
+
function parseChoice(answer, listLength) {
|
|
141
|
+
const trimmed = answer.trim().toLowerCase();
|
|
142
|
+
// Empty input is never a match — defense-in-depth even though
|
|
143
|
+
// the caller short-circuits "" as "skip". Without this, the
|
|
144
|
+
// substring loop below would resolve "" against every label.
|
|
145
|
+
if (!trimmed)
|
|
146
|
+
return null;
|
|
147
|
+
const asNumber = Number(trimmed);
|
|
148
|
+
if (Number.isInteger(asNumber) && asNumber >= 1 && asNumber <= listLength) {
|
|
149
|
+
return asNumber - 1;
|
|
150
|
+
}
|
|
151
|
+
// Word aliases — substring match against label or shortLabel. We
|
|
152
|
+
// keep this loose because the picker isn't latency-sensitive and
|
|
153
|
+
// it's friendlier than rejecting "frontend" because the label is
|
|
154
|
+
// "Frontend Web".
|
|
155
|
+
for (let i = 0; i < persona_samples_1.PERSONA_SAMPLES.length; i++) {
|
|
156
|
+
const p = persona_samples_1.PERSONA_SAMPLES[i];
|
|
157
|
+
if (trimmed === p.slug ||
|
|
158
|
+
p.label.toLowerCase().includes(trimmed) ||
|
|
159
|
+
p.shortLabel.toLowerCase() === trimmed) {
|
|
160
|
+
return i;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Test seam — internal pure helpers exported solely for unit
|
|
167
|
+
* coverage. Do not consume from non-spec code; the underscore
|
|
168
|
+
* prefix is the contract.
|
|
169
|
+
*/
|
|
170
|
+
exports.__test = { parseChoice, orderByFeatured };
|
|
171
|
+
//# sourceMappingURL=persona-picker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persona-picker.js","sourceRoot":"","sources":["../../src/lib/persona-picker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Static lookup table: persona slug → presentation data for the
|
|
4
|
+
* onboarding screens.
|
|
5
|
+
*
|
|
6
|
+
* Each entry carries the data the CLI needs to render the persona
|
|
7
|
+
* picker, the workspace-explainer card, and the build-flow handover
|
|
8
|
+
* box without a network call. Two pieces of justification:
|
|
9
|
+
*
|
|
10
|
+
* 1. The persona-pick step happens at `ritual init` time, before
|
|
11
|
+
* the workspace exists and before the user has approved any
|
|
12
|
+
* API calls. We want the picker to feel instant — no spinner
|
|
13
|
+
* while we hit `/templates`.
|
|
14
|
+
*
|
|
15
|
+
* 2. The discipline framing + sample exploration names are
|
|
16
|
+
* curation, not data the API has today. Keeping the curation
|
|
17
|
+
* CLI-side is fine: the underlying template (id matches the
|
|
18
|
+
* `slug` here) is what gets used downstream; this file is
|
|
19
|
+
* presentation polish.
|
|
20
|
+
*
|
|
21
|
+
* When a new Engineering template ships in
|
|
22
|
+
* `apps/api/scripts/templates/`, add a matching entry here. Persona
|
|
23
|
+
* slug MUST equal the template's `schema.id` (the JSON file's `id`
|
|
24
|
+
* field) — that's how `/ritual build` looks up the right default
|
|
25
|
+
* template at build time.
|
|
26
|
+
*
|
|
27
|
+
* Maintenance shape: this is ~12 entries × ~10 fields = a couple
|
|
28
|
+
* hundred lines, churns only when the Engineering template family
|
|
29
|
+
* grows. The seed pipeline doesn't read this file; this is
|
|
30
|
+
* CLI-render-time data only.
|
|
31
|
+
*/
|
|
32
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
33
|
+
exports.FEATURED_PERSONA_SLUGS = exports.GENERIC_PERSONA = exports.PERSONA_SAMPLES = void 0;
|
|
34
|
+
exports.findPersona = findPersona;
|
|
35
|
+
const colors_1 = require("./colors");
|
|
36
|
+
// Accents chosen to be visually distinct under 16-color and 256-color
|
|
37
|
+
// terminals as well as truecolor. Keep each persona in a different
|
|
38
|
+
// hue family so adjacent cards in the picker don't blend.
|
|
39
|
+
const ACCENT = {
|
|
40
|
+
teal: colors_1.RITUAL_TEAL,
|
|
41
|
+
blue: [0x4f, 0x9a, 0xff],
|
|
42
|
+
violet: [0x9b, 0x6f, 0xff],
|
|
43
|
+
magenta: [0xd8, 0x5f, 0xc0],
|
|
44
|
+
red: [0xe0, 0x5f, 0x5f],
|
|
45
|
+
amber: [0xe0, 0xa8, 0x4f],
|
|
46
|
+
green: [0x60, 0xc7, 0x70],
|
|
47
|
+
cyan: [0x5f, 0xc7, 0xc7],
|
|
48
|
+
};
|
|
49
|
+
exports.PERSONA_SAMPLES = [
|
|
50
|
+
{
|
|
51
|
+
slug: 'backend-services',
|
|
52
|
+
label: 'Backend Services',
|
|
53
|
+
shortLabel: 'Backend',
|
|
54
|
+
framing: 'backend services — APIs, workers, contracts, persistence',
|
|
55
|
+
sampleExplorations: [
|
|
56
|
+
'Add rate limit to /orders',
|
|
57
|
+
'Make Idempotency-Key required for POSTs',
|
|
58
|
+
'Split monolithic /search into focused services',
|
|
59
|
+
],
|
|
60
|
+
accent: ACCENT.teal,
|
|
61
|
+
caresAbout: ['APIs', 'workers', 'transactions', 'idempotency', 'tracing'],
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
slug: 'frontend-web',
|
|
65
|
+
label: 'Frontend Web',
|
|
66
|
+
shortLabel: 'Frontend',
|
|
67
|
+
framing: 'frontend web — components, state, perf, accessibility',
|
|
68
|
+
sampleExplorations: [
|
|
69
|
+
'Improve checkout LCP',
|
|
70
|
+
'Add empty state to settings page',
|
|
71
|
+
'Fix keyboard nav on /admin tabs',
|
|
72
|
+
],
|
|
73
|
+
accent: ACCENT.cyan,
|
|
74
|
+
caresAbout: ['components', 'state', 'routing', 'a11y', 'RUM', 'bundle'],
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
slug: 'data-engineering',
|
|
78
|
+
label: 'Data Engineering',
|
|
79
|
+
shortLabel: 'Data',
|
|
80
|
+
framing: 'data engineering — pipelines, schemas, lineage, SLAs',
|
|
81
|
+
sampleExplorations: [
|
|
82
|
+
'Add CDC for orders → fact_revenue',
|
|
83
|
+
'Handle late-arriving events in user_sessions',
|
|
84
|
+
'Deprecate fact_v1; cut consumers to fact_v2',
|
|
85
|
+
],
|
|
86
|
+
accent: ACCENT.blue,
|
|
87
|
+
caresAbout: ['ETL/ELT', 'schemas', 'lineage', 'freshness', 'backfills'],
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
slug: 'ml-engineering',
|
|
91
|
+
label: 'ML Engineering',
|
|
92
|
+
shortLabel: 'ML',
|
|
93
|
+
framing: 'ML engineering — datasets, training, eval, serving, drift',
|
|
94
|
+
sampleExplorations: [
|
|
95
|
+
'Experiment: new ranking model v4 vs v3',
|
|
96
|
+
'Add online drift detection for recs',
|
|
97
|
+
'Retraining cadence for fraud classifier',
|
|
98
|
+
],
|
|
99
|
+
accent: ACCENT.violet,
|
|
100
|
+
caresAbout: ['datasets', 'features', 'evals', 'serving', 'drift'],
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
slug: 'platform-engineering',
|
|
104
|
+
label: 'Platform Engineering',
|
|
105
|
+
shortLabel: 'Platform',
|
|
106
|
+
framing: 'platform — IaC, CI/CD, SLOs, observability, on-call',
|
|
107
|
+
sampleExplorations: [
|
|
108
|
+
'Set up SLO for /api endpoints (99.9%)',
|
|
109
|
+
'Add per-tenant rate limiting',
|
|
110
|
+
'Ephemeral preview env per PR',
|
|
111
|
+
],
|
|
112
|
+
accent: ACCENT.green,
|
|
113
|
+
caresAbout: ['IaC', 'CI/CD', 'SLOs', 'rollouts', 'observability'],
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
slug: 'security-engineering',
|
|
117
|
+
label: 'Security Engineering',
|
|
118
|
+
shortLabel: 'Security',
|
|
119
|
+
framing: 'security — threat models, controls, audit, supply chain',
|
|
120
|
+
sampleExplorations: [
|
|
121
|
+
'Threat model for /webhooks endpoint',
|
|
122
|
+
'Audit log retention for compliance',
|
|
123
|
+
'Rotate JWT signing keys quarterly',
|
|
124
|
+
],
|
|
125
|
+
accent: ACCENT.red,
|
|
126
|
+
caresAbout: ['threats', 'authN/Z', 'secrets', 'SAST/DAST', 'audit'],
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
slug: 'developer-tooling',
|
|
130
|
+
label: 'Developer Tooling',
|
|
131
|
+
shortLabel: 'DevTools',
|
|
132
|
+
framing: 'developer tooling — CLIs, MCPs, structured I/O, distribution',
|
|
133
|
+
sampleExplorations: [
|
|
134
|
+
'Add --json output to ritual init',
|
|
135
|
+
'MCP tool: generate eval report',
|
|
136
|
+
'Skill: lint imports in PR diffs',
|
|
137
|
+
],
|
|
138
|
+
accent: ACCENT.amber,
|
|
139
|
+
caresAbout: ['CLI UX', 'exit codes', 'JSON output', 'versioning', 'DX'],
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
slug: 'embedded-firmware',
|
|
143
|
+
label: 'Embedded / Firmware',
|
|
144
|
+
shortLabel: 'Embedded',
|
|
145
|
+
framing: 'embedded — MCU, RTOS, memory, peripherals, boot, OTA',
|
|
146
|
+
sampleExplorations: [
|
|
147
|
+
'OTA rollback safety check',
|
|
148
|
+
'Watchdog timeout for sensor task',
|
|
149
|
+
'Power budget for BLE advertising',
|
|
150
|
+
],
|
|
151
|
+
accent: ACCENT.green,
|
|
152
|
+
caresAbout: ['MCU', 'RTOS', 'memory', 'peripherals', 'OTA', 'power'],
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
slug: 'game-development',
|
|
156
|
+
label: 'Game Development',
|
|
157
|
+
shortLabel: 'Game Dev',
|
|
158
|
+
framing: 'game dev — engines, scenes, frame budget, assets',
|
|
159
|
+
sampleExplorations: [
|
|
160
|
+
'Weapon-charging mechanic in L1',
|
|
161
|
+
'Asset streaming for level 3',
|
|
162
|
+
'Frame budget for new VFX system',
|
|
163
|
+
],
|
|
164
|
+
accent: ACCENT.magenta,
|
|
165
|
+
caresAbout: ['engine', 'scenes', 'FPS', 'shaders', 'assets'],
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
slug: 'smart-contracts',
|
|
169
|
+
label: 'Smart Contracts',
|
|
170
|
+
shortLabel: 'Contracts',
|
|
171
|
+
framing: 'smart contracts — on-chain, gas, invariants, audits',
|
|
172
|
+
sampleExplorations: [
|
|
173
|
+
'Upgrade authority multisig (4-of-7)',
|
|
174
|
+
'Gas optimization for batch deposits',
|
|
175
|
+
'Invariant: totalSupply == sum(balances)',
|
|
176
|
+
],
|
|
177
|
+
accent: ACCENT.amber,
|
|
178
|
+
caresAbout: ['state', 'gas', 'invariants', 'oracles', 'audits'],
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
slug: 'desktop-apps',
|
|
182
|
+
label: 'Desktop Apps',
|
|
183
|
+
shortLabel: 'Desktop',
|
|
184
|
+
framing: 'desktop apps — OS APIs, installers, signing, auto-update',
|
|
185
|
+
sampleExplorations: [
|
|
186
|
+
'Auto-update rollback on first-launch crash',
|
|
187
|
+
'macOS notarization in CI',
|
|
188
|
+
'Menu bar app + Windows tray parity',
|
|
189
|
+
],
|
|
190
|
+
accent: ACCENT.cyan,
|
|
191
|
+
caresAbout: ['OS APIs', 'installers', 'signing', 'updates', 'crashes'],
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
slug: 'qa-engineering',
|
|
195
|
+
label: 'QA Engineering',
|
|
196
|
+
shortLabel: 'QA',
|
|
197
|
+
framing: 'QA — test strategy, harness, flake mgmt, release gates',
|
|
198
|
+
sampleExplorations: [
|
|
199
|
+
'Contract tests between web ↔ api',
|
|
200
|
+
'Flake quarantine policy + SLA',
|
|
201
|
+
'Release-blocking gate definition',
|
|
202
|
+
],
|
|
203
|
+
accent: ACCENT.blue,
|
|
204
|
+
caresAbout: ['test pyramid', 'harnesses', 'flakes', 'contracts', 'CI cost'],
|
|
205
|
+
},
|
|
206
|
+
];
|
|
207
|
+
/** Look up a persona by slug. Returns null for unknown slugs. */
|
|
208
|
+
function findPersona(slug) {
|
|
209
|
+
if (!slug)
|
|
210
|
+
return null;
|
|
211
|
+
return exports.PERSONA_SAMPLES.find((p) => p.slug === slug) ?? null;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Generic fallback persona used when the user has skipped the picker
|
|
215
|
+
* (e.g. `--persona none` or non-TTY automation). Lets the workspace
|
|
216
|
+
* explainer + build-flow explainer still render with sensible
|
|
217
|
+
* defaults instead of crashing on null.
|
|
218
|
+
*/
|
|
219
|
+
exports.GENERIC_PERSONA = {
|
|
220
|
+
slug: 'backend-services', // safe default; never persisted unless picked
|
|
221
|
+
label: 'Software Engineer',
|
|
222
|
+
shortLabel: 'Engineer',
|
|
223
|
+
framing: 'software — features, refactors, investigations',
|
|
224
|
+
sampleExplorations: [
|
|
225
|
+
'New feature from a brief',
|
|
226
|
+
'Refactor existing code',
|
|
227
|
+
'Investigation before coding',
|
|
228
|
+
],
|
|
229
|
+
accent: colors_1.RITUAL_TEAL,
|
|
230
|
+
caresAbout: ['features', 'tests', 'rollout', 'review'],
|
|
231
|
+
};
|
|
232
|
+
/**
|
|
233
|
+
* The 5 personas surfaced first in the picker — by rough community
|
|
234
|
+
* frequency. The rest are revealed via "see more." Order tuned for
|
|
235
|
+
* the most common backend/frontend/data starting points, with
|
|
236
|
+
* platform + ML following.
|
|
237
|
+
*/
|
|
238
|
+
exports.FEATURED_PERSONA_SLUGS = [
|
|
239
|
+
'backend-services',
|
|
240
|
+
'frontend-web',
|
|
241
|
+
'data-engineering',
|
|
242
|
+
'ml-engineering',
|
|
243
|
+
'platform-engineering',
|
|
244
|
+
];
|
|
245
|
+
//# sourceMappingURL=persona-samples.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persona-samples.js","sourceRoot":"","sources":["../../src/lib/persona-samples.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-config.js","sourceRoot":"","sources":["../../src/lib/project-config.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"project-config.js","sourceRoot":"","sources":["../../src/lib/project-config.ts"],"names":[],"mappings":";;AA8DA,oDAEC;AAOD,8CAeC;AAUD,8CAIC;AApGD,qCAA6E;AAC7E,yCAA0C;AA0D1C,MAAM,sBAAsB,GAAG,SAAS,CAAC;AACzC,MAAM,uBAAuB,GAAG,aAAa,CAAC;AAE9C,SAAgB,oBAAoB,CAAC,UAAkB;IACtD,OAAO,IAAA,gBAAI,EAAC,UAAU,EAAE,sBAAsB,EAAE,uBAAuB,CAAC,CAAC;AAC1E,CAAC;AAED;;;;GAIG;AACH,SAAgB,iBAAiB,CAAC,UAAkB;IACnD,MAAM,CAAC,GAAG,oBAAoB,CAAC,UAAU,CAAC,CAAC;IAC3C,IAAI,CAAC,IAAA,oBAAU,EAAC,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAChC,IAAI,CAAC;QACJ,MAAM,GAAG,GAAG,IAAA,sBAAY,EAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QACrC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAkB,CAAC;QAChD,8DAA8D;QAC9D,gEAAgE;QAChE,8BAA8B;QAC9B,IAAI,MAAM,CAAC,OAAO,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QACtC,IAAI,CAAC,MAAM,CAAC,WAAW,IAAI,OAAO,MAAM,CAAC,WAAW,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC;QAC/E,OAAO,MAAM,CAAC;IACf,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,IAAI,CAAC;IACb,CAAC;AACF,CAAC;AAED;;;;;;;GAOG;AACH,SAAgB,iBAAiB,CAAC,UAAkB,EAAE,MAAqB;IAC1E,MAAM,CAAC,GAAG,oBAAoB,CAAC,UAAU,CAAC,CAAC;IAC3C,IAAA,mBAAS,EAAC,IAAA,mBAAO,EAAC,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3C,IAAA,uBAAa,EAAC,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC;AACnE,CAAC"}
|