happy-stacks 0.6.6 → 0.6.7
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.
|
@@ -45,7 +45,7 @@ Progress tracking (update manually while auditing):
|
|
|
45
45
|
- Next unreviewed commit: n/a (complete)
|
|
46
46
|
- Pass 2 full-diff verification markers: `249/249` (each `## NNN` has a `Pass2FullDiff:` line; patch artifacts under `/tmp/leeroy-wip-pass2/NNN.patch`)
|
|
47
47
|
- Pass 2 diff capture: `249/249` (`/tmp/leeroy-wip-pass2/NNN.patch` exists; hash/size recorded in each `Pass2FullDiff:` line)
|
|
48
|
-
- Pass 2 notes verification (manual): `
|
|
48
|
+
- Pass 2 notes verification (manual): `17/249` (this requires reading the patch and confirming/updating `### Manual Review Notes`)
|
|
49
49
|
|
|
50
50
|
Current state (2026-01-24):
|
|
51
51
|
|
|
@@ -363,7 +363,7 @@ Pass2FullDiff: CAPTURED at 2026-01-24T17:39:06+0100 sha=c2d3507357dc patchFile=/
|
|
|
363
363
|
---
|
|
364
364
|
|
|
365
365
|
## 012 2026-01-17 207ef1b2f572 `dev`
|
|
366
|
-
Pass2FullDiff: CAPTURED at 2026-01-24T17:39:06+0100 sha=207ef1b2f572 patchFile=/tmp/leeroy-wip-pass2/012.patch patchSha256=a9b3dfe31a3465be8415ccab235bb3bef26cb918530e86d596b6075891c94423 patchBytes=11240 patchLines=240 notesReviewed=
|
|
366
|
+
Pass2FullDiff: CAPTURED at 2026-01-24T17:39:06+0100 sha=207ef1b2f572 patchFile=/tmp/leeroy-wip-pass2/012.patch patchSha256=a9b3dfe31a3465be8415ccab235bb3bef26cb918530e86d596b6075891c94423 patchBytes=11240 patchLines=240 notesReviewed=yes reviewedAt=2026-01-24T18:10:19+0100 notesUpdated=no
|
|
367
367
|
|
|
368
368
|
- Subject: fix(dev): gate CLI detection logging
|
|
369
369
|
- Reasons: full manual review coverage (was not in the manual-review queue)
|
|
@@ -388,7 +388,7 @@ Pass2FullDiff: CAPTURED at 2026-01-24T17:39:06+0100 sha=207ef1b2f572 patchFile=/
|
|
|
388
388
|
---
|
|
389
389
|
|
|
390
390
|
## 013 2026-01-17 58a892d413d1 `command-palette`
|
|
391
|
-
Pass2FullDiff: CAPTURED at 2026-01-24T17:39:06+0100 sha=58a892d413d1 patchFile=/tmp/leeroy-wip-pass2/013.patch patchSha256=1a11a0e1395cd3aa82663418fb8d16080ee1348ac4e44b1c39132dd733b6ee00 patchBytes=1434 patchLines=36 notesReviewed=
|
|
391
|
+
Pass2FullDiff: CAPTURED at 2026-01-24T17:39:06+0100 sha=58a892d413d1 patchFile=/tmp/leeroy-wip-pass2/013.patch patchSha256=1a11a0e1395cd3aa82663418fb8d16080ee1348ac4e44b1c39132dd733b6ee00 patchBytes=1434 patchLines=36 notesReviewed=yes reviewedAt=2026-01-24T18:10:19+0100 notesUpdated=no
|
|
392
392
|
|
|
393
393
|
- Subject: fix(command-palette): include navigate dependency
|
|
394
394
|
- Reasons: full manual review coverage (was not in the manual-review queue)
|
|
@@ -412,7 +412,7 @@ Pass2FullDiff: CAPTURED at 2026-01-24T17:39:06+0100 sha=58a892d413d1 patchFile=/
|
|
|
412
412
|
---
|
|
413
413
|
|
|
414
414
|
## 014 2026-01-17 41479b35415f `env`
|
|
415
|
-
Pass2FullDiff: CAPTURED at 2026-01-24T17:39:06+0100 sha=41479b35415f patchFile=/tmp/leeroy-wip-pass2/014.patch patchSha256=0a14bef9963c50010d2c6baa8bdc255195f7ac07b50ecece4fcaf9c0fcd9a657 patchBytes=5851 patchLines=141 notesReviewed=
|
|
415
|
+
Pass2FullDiff: CAPTURED at 2026-01-24T17:39:06+0100 sha=41479b35415f patchFile=/tmp/leeroy-wip-pass2/014.patch patchSha256=0a14bef9963c50010d2c6baa8bdc255195f7ac07b50ecece4fcaf9c0fcd9a657 patchBytes=5851 patchLines=141 notesReviewed=yes reviewedAt=2026-01-24T18:10:19+0100 notesUpdated=no
|
|
416
416
|
|
|
417
417
|
- Subject: feat(env): add env var template parsing
|
|
418
418
|
- Reasons: full manual review coverage (was not in the manual-review queue)
|
|
@@ -440,7 +440,7 @@ Pass2FullDiff: CAPTURED at 2026-01-24T17:39:06+0100 sha=41479b35415f patchFile=/
|
|
|
440
440
|
---
|
|
441
441
|
|
|
442
442
|
## 015 2026-01-17 695bcd09eb9e `env`
|
|
443
|
-
Pass2FullDiff: CAPTURED at 2026-01-24T17:39:06+0100 sha=695bcd09eb9e patchFile=/tmp/leeroy-wip-pass2/015.patch patchSha256=2ce8f5113f7e010edb0f7ddce7fa3f1ad2ef7e7f57b8074c9ad0d46707d5d2b5 patchBytes=24232 patchLines=540 notesReviewed=
|
|
443
|
+
Pass2FullDiff: CAPTURED at 2026-01-24T17:39:06+0100 sha=695bcd09eb9e patchFile=/tmp/leeroy-wip-pass2/015.patch patchSha256=2ce8f5113f7e010edb0f7ddce7fa3f1ad2ef7e7f57b8074c9ad0d46707d5d2b5 patchBytes=24232 patchLines=540 notesReviewed=yes reviewedAt=2026-01-24T18:10:19+0100 notesUpdated=no
|
|
444
444
|
|
|
445
445
|
- Subject: fix(env): improve remote env resolution and previews
|
|
446
446
|
- Reasons: full manual review coverage (was not in the manual-review queue)
|
|
@@ -474,7 +474,7 @@ Pass2FullDiff: CAPTURED at 2026-01-24T17:39:06+0100 sha=695bcd09eb9e patchFile=/
|
|
|
474
474
|
---
|
|
475
475
|
|
|
476
476
|
## 016 2026-01-17 6cdb90a49aad `env`
|
|
477
|
-
Pass2FullDiff: CAPTURED at 2026-01-24T17:39:06+0100 sha=6cdb90a49aad patchFile=/tmp/leeroy-wip-pass2/016.patch patchSha256=c1429ac752ff6a5828610cd00f89c3490559f5ebdde07fa158afececee5239fb patchBytes=90044 patchLines=2144 notesReviewed=
|
|
477
|
+
Pass2FullDiff: CAPTURED at 2026-01-24T17:39:06+0100 sha=6cdb90a49aad patchFile=/tmp/leeroy-wip-pass2/016.patch patchSha256=c1429ac752ff6a5828610cd00f89c3490559f5ebdde07fa158afececee5239fb patchBytes=90044 patchLines=2144 notesReviewed=yes reviewedAt=2026-01-24T18:10:19+0100 notesUpdated=no
|
|
478
478
|
|
|
479
479
|
- Subject: feat(env): update env var list, cards, and preview modal
|
|
480
480
|
- Reasons: full manual review coverage (was not in the manual-review queue)
|
|
@@ -510,7 +510,7 @@ Pass2FullDiff: CAPTURED at 2026-01-24T17:39:06+0100 sha=6cdb90a49aad patchFile=/
|
|
|
510
510
|
---
|
|
511
511
|
|
|
512
512
|
## 017 2026-01-17 65bae55a0b61 `i18n`
|
|
513
|
-
Pass2FullDiff: CAPTURED at 2026-01-24T17:39:06+0100 sha=65bae55a0b61 patchFile=/tmp/leeroy-wip-pass2/017.patch patchSha256=9734e2764a6330f2d829d9fd3a1e995d14127da3449088ffb2335f5a732ba331 patchBytes=181014 patchLines=3802 notesReviewed=
|
|
513
|
+
Pass2FullDiff: CAPTURED at 2026-01-24T17:39:06+0100 sha=65bae55a0b61 patchFile=/tmp/leeroy-wip-pass2/017.patch patchSha256=9734e2764a6330f2d829d9fd3a1e995d14127da3449088ffb2335f5a732ba331 patchBytes=181014 patchLines=3802 notesReviewed=yes reviewedAt=2026-01-24T18:10:19+0100 notesUpdated=yes
|
|
514
514
|
|
|
515
515
|
- Subject: refactor(i18n): separate translation types and content
|
|
516
516
|
- Reasons: large change (+1756/-1006)
|
package/package.json
CHANGED
package/scripts/setup.mjs
CHANGED
|
@@ -262,59 +262,37 @@ async function maybeConfigureAuthDefaults({ rootDir, profile, interactive }) {
|
|
|
262
262
|
`Recommended: set up a dedicated ${cyan('dev-auth')} seed stack so you authenticate once, then new stacks “just work”.`
|
|
263
263
|
)
|
|
264
264
|
);
|
|
265
|
+
const seedChoice = 'dev-auth';
|
|
266
|
+
const linkChoice = 'link';
|
|
265
267
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
268
|
+
if (!sources.hasDevAuthAccessKey) {
|
|
269
|
+
const wantLoginNow = await withRl(async (rl) => {
|
|
270
|
+
return await promptSelect(rl, {
|
|
271
|
+
title:
|
|
272
|
+
`${bold('Sign in now?')}\n` +
|
|
273
|
+
`${dim('This will create a dedicated dev-auth seed stack and walk you through a guided login in the browser.')}\n` +
|
|
274
|
+
`${dim('After this, new stacks can reuse your auth automatically (recommended).')}`,
|
|
275
|
+
options: [
|
|
276
|
+
{ label: `yes (${green('recommended')}) — sign in now`, value: true },
|
|
277
|
+
{ label: `no — I will do this later`, value: false },
|
|
278
|
+
],
|
|
279
|
+
defaultIndex: 0,
|
|
280
|
+
});
|
|
276
281
|
});
|
|
277
|
-
}
|
|
278
|
-
if (sources.hasMainAccessKey) {
|
|
279
|
-
options.push({ label: `use ${cyan('main')} as seed — fast, but shares identity with main`, value: 'main' });
|
|
280
|
-
}
|
|
281
|
-
if (sources.hasLegacyAccessKey) {
|
|
282
|
-
options.push({ label: `use legacy ${cyan('~/.happy')} as seed — best-effort`, value: 'legacy' });
|
|
283
|
-
}
|
|
284
|
-
options.push({ label: `skip for now — you can do this later`, value: 'skip' });
|
|
285
282
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
});
|
|
292
|
-
});
|
|
283
|
+
if (!wantLoginNow) {
|
|
284
|
+
// eslint-disable-next-line no-console
|
|
285
|
+
console.log(dim(`Tip: run ${yellow('happys stack create-dev-auth-seed dev-auth --login')} anytime to sign in.`));
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
293
288
|
|
|
294
|
-
|
|
289
|
+
// Guided wizard: creates stack, starts temporary UI/server, stores dev key (optional), logs in CLI.
|
|
290
|
+
await runNodeScript({ rootDir, rel: 'scripts/stack.mjs', args: ['create-dev-auth-seed', 'dev-auth', '--login'] });
|
|
291
|
+
} else {
|
|
295
292
|
// eslint-disable-next-line no-console
|
|
296
|
-
console.log(dim(`
|
|
297
|
-
return;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
const seedChoice = choice === 'create-dev-auth' || choice === 'use-dev-auth' ? 'dev-auth' : String(choice);
|
|
301
|
-
if (choice === 'create-dev-auth') {
|
|
302
|
-
// Guided wizard: creates stack, starts temporary UI/server, saves dev key (optional), logs in CLI.
|
|
303
|
-
await runNodeScript({ rootDir, rel: 'scripts/stack.mjs', args: ['create-dev-auth-seed', 'dev-auth'] });
|
|
293
|
+
console.log(dim(`Found an existing ${cyan('dev-auth')} seed stack; configuring auth reuse for new stacks.`));
|
|
304
294
|
}
|
|
305
295
|
|
|
306
|
-
// Symlink vs copy for seeded stacks (preferred: symlink so credentials stay up to date).
|
|
307
|
-
const linkChoice = await withRl(async (rl) => {
|
|
308
|
-
return await promptSelect(rl, {
|
|
309
|
-
title: `${bold('Auth seeding mode')}\n${dim('When seeding credentials into stacks, should we symlink or copy?')}`,
|
|
310
|
-
options: [
|
|
311
|
-
{ label: `symlink (${green('recommended')}) — stays up to date`, value: 'link' },
|
|
312
|
-
{ label: `copy — more isolated per stack`, value: 'copy' },
|
|
313
|
-
],
|
|
314
|
-
defaultIndex: 0,
|
|
315
|
-
});
|
|
316
|
-
});
|
|
317
|
-
|
|
318
296
|
await ensureEnvLocalUpdated({
|
|
319
297
|
rootDir,
|
|
320
298
|
updates: [
|
|
@@ -333,14 +311,15 @@ async function maybeConfigureAuthDefaults({ rootDir, profile, interactive }) {
|
|
|
333
311
|
if (candidateTargets.length) {
|
|
334
312
|
const seedNow = await withRl(async (rl) => {
|
|
335
313
|
return await promptSelect(rl, {
|
|
336
|
-
title:
|
|
337
|
-
|
|
338
|
-
|
|
314
|
+
title:
|
|
315
|
+
`${bold('Apply sign-in to existing stacks?')}\n` +
|
|
316
|
+
`${dim(`We found ${candidateTargets.length} existing stack(s) that could reuse your auth automatically.`)}\n` +
|
|
317
|
+
`${dim('This can fix “auth required / no machine” without re-login.')}`,
|
|
339
318
|
options: [
|
|
340
|
-
{ label: `yes —
|
|
341
|
-
{ label: 'no
|
|
319
|
+
{ label: `yes (${green('recommended')}) — apply to ${candidateTargets.length} stack(s) now`, value: true },
|
|
320
|
+
{ label: 'no — leave them as-is', value: false },
|
|
342
321
|
],
|
|
343
|
-
defaultIndex:
|
|
322
|
+
defaultIndex: 0,
|
|
344
323
|
});
|
|
345
324
|
});
|
|
346
325
|
if (seedNow) {
|
|
@@ -360,7 +339,7 @@ async function maybeConfigureAuthDefaults({ rootDir, profile, interactive }) {
|
|
|
360
339
|
console.log(dim('No existing stacks detected that need seeding (nothing to do).'));
|
|
361
340
|
}
|
|
362
341
|
|
|
363
|
-
// Dev key UX (for phone/Playwright restores).
|
|
342
|
+
// Dev key UX (for phone/Playwright restores).
|
|
364
343
|
const sourcesAfter = detectAuthSources();
|
|
365
344
|
if (sourcesAfter.hasDevKey) {
|
|
366
345
|
// eslint-disable-next-line no-console
|
|
@@ -371,19 +350,8 @@ async function maybeConfigureAuthDefaults({ rootDir, profile, interactive }) {
|
|
|
371
350
|
console.log(dim('This lets you restore the UI account quickly (and can help automation).'));
|
|
372
351
|
// eslint-disable-next-line no-console
|
|
373
352
|
console.log(dim(`Stored at: ${sourcesAfter.devKeyPath}`));
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
title: 'Do you want to print it now?',
|
|
377
|
-
options: [
|
|
378
|
-
{ label: `yes — print dev key (${yellow('will display a secret')})`, value: 'print' },
|
|
379
|
-
{ label: 'no (default) — keep it private', value: 'skip' },
|
|
380
|
-
],
|
|
381
|
-
defaultIndex: 1,
|
|
382
|
-
});
|
|
383
|
-
});
|
|
384
|
-
if (keyChoice === 'print') {
|
|
385
|
-
await runNodeScript({ rootDir, rel: 'scripts/auth.mjs', args: ['dev-key', '--print'] });
|
|
386
|
-
}
|
|
353
|
+
// eslint-disable-next-line no-console
|
|
354
|
+
console.log(dim(`Tip: to print it later, run: ${yellow('happys auth dev-key --print')}`));
|
|
387
355
|
} else {
|
|
388
356
|
// eslint-disable-next-line no-console
|
|
389
357
|
console.log(dim(`Tip: to store a dev key later, run: ${yellow('happys auth dev-key --set "<key>"')}`));
|
package/scripts/stack.mjs
CHANGED
|
@@ -2158,6 +2158,8 @@ async function cmdCreateDevAuthSeed({ rootDir, argv }) {
|
|
|
2158
2158
|
const serverComponent = (kv.get('--server') ?? '').trim() || 'happy-server-light';
|
|
2159
2159
|
const interactive = !flags.has('--non-interactive') && (flags.has('--interactive') || isTty());
|
|
2160
2160
|
const bindMode = resolveBindModeFromArgs({ flags, kv });
|
|
2161
|
+
const forceLogin =
|
|
2162
|
+
flags.has('--login') ? true : flags.has('--no-login') || flags.has('--skip-login') ? false : null;
|
|
2161
2163
|
|
|
2162
2164
|
if (json) {
|
|
2163
2165
|
// Keep JSON mode non-interactive and stable by using the existing stack command output.
|
|
@@ -2206,14 +2208,17 @@ async function cmdCreateDevAuthSeed({ rootDir, argv }) {
|
|
|
2206
2208
|
if (interactive) {
|
|
2207
2209
|
await withRl(async (rl) => {
|
|
2208
2210
|
let savedDevKey = false;
|
|
2209
|
-
const wantLogin =
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2211
|
+
const wantLogin =
|
|
2212
|
+
forceLogin != null
|
|
2213
|
+
? forceLogin
|
|
2214
|
+
: await promptSelect(rl, {
|
|
2215
|
+
title: `${bold('dev-auth seed stack')}\n${dim('Recommended: do the guided login now so the seed is ready immediately.')}`,
|
|
2216
|
+
options: [
|
|
2217
|
+
{ label: `yes (${green('recommended')}) — start temporary server + UI and log in`, value: true },
|
|
2218
|
+
{ label: `no — I will do this later`, value: false },
|
|
2219
|
+
],
|
|
2220
|
+
defaultIndex: 0,
|
|
2221
|
+
});
|
|
2217
2222
|
|
|
2218
2223
|
if (wantLogin) {
|
|
2219
2224
|
console.log('');
|
|
@@ -3531,7 +3536,7 @@ async function main() {
|
|
|
3531
3536
|
' happys stack duplicate <from> <to> [--duplicate-worktrees] [--deps=none|link|install|link-or-install] [--json]',
|
|
3532
3537
|
' happys stack info <name> [--json]',
|
|
3533
3538
|
' happys stack pr <name> --happy=<pr-url|number> [--happy-server-light=<pr-url|number>] [--dev|--start] [--json] [-- ...]',
|
|
3534
|
-
' happys stack create-dev-auth-seed [name] [--server=happy-server|happy-server-light] [--non-interactive] [--json]',
|
|
3539
|
+
' happys stack create-dev-auth-seed [name] [--server=happy-server|happy-server-light] [--login|--no-login] [--non-interactive] [--json]',
|
|
3535
3540
|
' happys stack daemon <name> start|stop|restart|status [--json]',
|
|
3536
3541
|
' happys stack happy <name> [-- ...]',
|
|
3537
3542
|
' happys stack env <name> set KEY=VALUE [KEY2=VALUE2...] | unset KEY [KEY2...] | get KEY | list | path [--json]',
|