projecta-rrr 1.24.2 → 1.24.4

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 CHANGED
@@ -4,6 +4,18 @@ All notable changes to RRR will be documented in this file.
4
4
 
5
5
  Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
6
6
 
7
+ ## [1.24.4] - 2026-05-12
8
+
9
+ ### Fixed
10
+ - **Sprite browser UAT readiness** — live Sprite status now fails when `.planning/RUNTIME.json` requests `gsd-browser` but the Sprite runtime does not have `gsd-browser` on `PATH`.
11
+
12
+ ## [1.24.3] - 2026-05-12
13
+
14
+ ### Fixed
15
+ - **Sprite GitHub auth** — live provisioning now passes a local `GITHUB_TOKEN`, `GH_TOKEN`, or `gh auth token` into every Git/GitHub Sprite command without writing the token into `.planning`.
16
+ - **Sprite checkout** — branch checkout now configures GitHub CLI's Git credential helper inside the same token-scoped command before running `git fetch`.
17
+ - **Sprite checkpoints** — provisioning only creates the clean-ready checkpoint after clone, checkout, RRR install, and setup all pass.
18
+
7
19
  ## [1.24.2] - 2026-05-12
8
20
 
9
21
  ### Fixed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "projecta-rrr",
3
- "version": "1.24.2",
3
+ "version": "1.24.4",
4
4
  "description": "A meta-prompting, context engineering and spec-driven development system for Claude Code by Projecta.ai",
5
5
  "bin": {
6
6
  "projecta-rrr": "bin/install.js",
@@ -213,7 +213,7 @@ function buildSpriteProvisionPlan(projectRoot, options) {
213
213
  const cloneCommand = repo
214
214
  ? `gh repo clone ${repo} ${workdir}`
215
215
  : `git clone <repo-url> ${workdir}`;
216
- const checkoutCommand = `git fetch origin && git checkout -B ${teamConfig.branch} origin/${config.github.base_branch}`;
216
+ const checkoutCommand = `gh auth setup-git >/dev/null 2>&1 || true; git fetch origin && git checkout -B ${teamConfig.branch} origin/${config.github.base_branch}`;
217
217
 
218
218
  rows.push({
219
219
  team,
@@ -228,8 +228,9 @@ function buildSpriteProvisionPlan(projectRoot, options) {
228
228
  commands: [
229
229
  `sprite create ${teamConfig.sprite} --skip-console`,
230
230
  `sprite exec -s ${teamConfig.sprite} -- mkdir -p /home/sprite/work`,
231
- `sprite exec -s ${teamConfig.sprite} -- bash -lc 'test -d ${workdir}/.git || ${cloneCommand}'`,
232
- `sprite exec -s ${teamConfig.sprite} --dir ${workdir} -- bash -lc '${checkoutCommand}'`,
231
+ `sprite exec -s ${teamConfig.sprite} --env GITHUB_TOKEN=$GITHUB_TOKEN -- bash -lc 'gh auth status || echo "Run gh auth login in this Sprite, or apply provisioning from a machine with GITHUB_TOKEN/GH_TOKEN/gh auth token"'`,
232
+ `sprite exec -s ${teamConfig.sprite} --env GITHUB_TOKEN=$GITHUB_TOKEN -- bash -lc 'test -d ${workdir}/.git || ${cloneCommand}'`,
233
+ `sprite exec -s ${teamConfig.sprite} --dir ${workdir} --env GITHUB_TOKEN=$GITHUB_TOKEN -- bash -lc '${checkoutCommand}'`,
233
234
  `sprite exec -s ${teamConfig.sprite} --dir ${workdir} -- npx projecta-rrr@latest --global --yes`,
234
235
  ...setup.map(cmd => `sprite exec -s ${teamConfig.sprite} --dir ${workdir} -- bash -lc '${cmd}'`),
235
236
  `sprite checkpoint create -s ${teamConfig.sprite} --comment "rrr clean-ready ${config.milestone} ${team}"`
@@ -316,18 +317,73 @@ function execCapture(command, args, options) {
316
317
  }
317
318
  }
318
319
 
320
+ function normalizeCreateResult(result) {
321
+ if (!result.ok && /already exists/i.test(result.output || '')) {
322
+ return { ...result, ok: true, output: result.output || 'sprite already exists' };
323
+ }
324
+ return result;
325
+ }
326
+
327
+ function localGitHubToken(projectRoot) {
328
+ if (process.env.GITHUB_TOKEN) return process.env.GITHUB_TOKEN;
329
+ if (process.env.GH_TOKEN) return process.env.GH_TOKEN;
330
+ const token = execCapture('gh', ['auth', 'token'], { cwd: projectRoot });
331
+ return token.ok && token.output ? token.output.trim() : '';
332
+ }
333
+
334
+ function githubTokenEnvArgs(token) {
335
+ return token ? ['--env', `GITHUB_TOKEN=${token}`] : [];
336
+ }
337
+
338
+ function githubAuthStep(row, token) {
339
+ if (token) {
340
+ return execCapture('sprite', [
341
+ 'exec',
342
+ '-s',
343
+ row.sprite,
344
+ ...githubTokenEnvArgs(token),
345
+ '--',
346
+ 'gh',
347
+ 'auth',
348
+ 'status'
349
+ ]);
350
+ }
351
+ return execCapture('sprite', ['exec', '-s', row.sprite, '--', 'gh', 'auth', 'status']);
352
+ }
353
+
354
+ function gitExecArgs(row, token) {
355
+ return [
356
+ 'exec',
357
+ '-s',
358
+ row.sprite,
359
+ ...githubTokenEnvArgs(token)
360
+ ];
361
+ }
362
+
363
+ function gitExecArgsInWorkdir(row, token) {
364
+ return [
365
+ 'exec',
366
+ '-s',
367
+ row.sprite,
368
+ '--dir',
369
+ row.workdir,
370
+ ...githubTokenEnvArgs(token)
371
+ ];
372
+ }
373
+
319
374
  function applySpriteProvisionPlan(projectRoot, options) {
320
375
  const plan = buildSpriteProvisionPlan(projectRoot, options);
321
376
  const results = [];
322
377
  for (const row of plan.rows) {
378
+ const token = localGitHubToken(projectRoot);
323
379
  const teamResults = [];
324
- const create = execCapture('sprite', ['create', row.sprite, '--skip-console']);
380
+ const create = normalizeCreateResult(execCapture('sprite', ['create', row.sprite, '--skip-console']));
325
381
  teamResults.push({ step: 'create', ...create });
326
382
  execCapture('sprite', ['exec', '-s', row.sprite, '--', 'mkdir', '-p', '/home/sprite/work']);
383
+ const auth = githubAuthStep(row, token);
384
+ teamResults.push({ step: 'github-auth', ...auth, output: auth.ok ? 'authenticated' : auth.output });
327
385
  const clone = execCapture('sprite', [
328
- 'exec',
329
- '-s',
330
- row.sprite,
386
+ ...gitExecArgs(row, token),
331
387
  '--',
332
388
  'bash',
333
389
  '-lc',
@@ -335,15 +391,11 @@ function applySpriteProvisionPlan(projectRoot, options) {
335
391
  ]);
336
392
  teamResults.push({ step: 'clone', ...clone });
337
393
  const checkout = execCapture('sprite', [
338
- 'exec',
339
- '-s',
340
- row.sprite,
341
- '--dir',
342
- row.workdir,
394
+ ...gitExecArgsInWorkdir(row, token),
343
395
  '--',
344
396
  'bash',
345
397
  '-lc',
346
- `git fetch origin && git checkout -B ${row.branch} origin/${plan.config.github.base_branch}`
398
+ `gh auth setup-git >/dev/null 2>&1 || true; git fetch origin && git checkout -B ${row.branch} origin/${plan.config.github.base_branch}`
347
399
  ]);
348
400
  teamResults.push({ step: 'checkout', ...checkout });
349
401
  const rrr = execCapture('sprite', [
@@ -363,14 +415,17 @@ function applySpriteProvisionPlan(projectRoot, options) {
363
415
  const setup = execCapture('sprite', ['exec', '-s', row.sprite, '--dir', row.workdir, '--', 'bash', '-lc', command]);
364
416
  teamResults.push({ step: `setup: ${command}`, ...setup });
365
417
  }
366
- const checkpoint = execCapture('sprite', [
367
- 'checkpoint',
368
- 'create',
369
- '-s',
370
- row.sprite,
371
- '--comment',
372
- `rrr clean-ready ${plan.config.milestone} ${row.team}`
373
- ]);
418
+ const readyForCheckpoint = teamResults.every(result => result.ok);
419
+ const checkpoint = readyForCheckpoint
420
+ ? execCapture('sprite', [
421
+ 'checkpoint',
422
+ 'create',
423
+ '-s',
424
+ row.sprite,
425
+ '--comment',
426
+ `rrr clean-ready ${plan.config.milestone} ${row.team}`
427
+ ])
428
+ : { ok: false, output: 'skipped because bootstrap failed' };
374
429
  teamResults.push({ step: 'checkpoint', ...checkpoint });
375
430
  results.push({ team: row.team, sprite: row.sprite, results: teamResults });
376
431
  }
@@ -410,8 +465,14 @@ function readSpriteStatus(projectRoot, options) {
410
465
  '-lc',
411
466
  'printf "branch="; git branch --show-current; printf "\\nhead="; git rev-parse --short HEAD; printf "\\nclaude="; claude --version 2>/dev/null || true; printf "\\ngsd="; gsd-browser --version 2>/dev/null || true'
412
467
  ]);
413
- status.ok = probe.ok;
468
+ const needsGsd = (plan.runtime.uat && plan.runtime.uat.browser === 'gsd-browser') ||
469
+ (((plan.runtime.tools || {}).developer_sprite || []).includes('gsd-browser'));
470
+ const hasGsd = /(^|\n)gsd=.+/.test(probe.output || '');
471
+ status.ok = probe.ok && (!needsGsd || hasGsd);
414
472
  status.details.push(probe.output || (probe.ok ? 'ok' : 'probe failed'));
473
+ if (probe.ok && needsGsd && !hasGsd) {
474
+ status.details.push('gsd-browser missing from Sprite runtime');
475
+ }
415
476
  } else {
416
477
  const list = execCapture('sprite', ['list', '--prefix', row.sprite]);
417
478
  status.ok = list.ok && list.output.includes(row.sprite);