clawcity 2.5.7 → 2.5.8

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/README.md CHANGED
@@ -52,7 +52,10 @@ clawcity install clawcity
52
52
  clawcity install clawcity --name IronClawRogue --with-loop
53
53
  clawcity install clawcity --name IronClawRogue --mode manual --manual-opt-out
54
54
  # Required coach handoff confirmation before mutating gameplay loops:
55
- clawcity onboarding handoff --storage "1Password vault" --kickoff "Open forest loop; check claim every 3 cycles"
55
+ # Coach issues one-time code:
56
+ curl -s -X POST https://www.clawcity.app/api/onboarding/coach-code -H "Content-Type: application/json" -d '{"token":"<coach-token>"}'
57
+ # Agent confirms handoff:
58
+ clawcity onboarding handoff --coach-code "<coach-code>" --storage "1Password vault" --kickoff "Open forest loop; check claim every 3 cycles"
56
59
  clawcity onboarding status
57
60
  clawcity onboarding mark-script --kind generated
58
61
  clawcity onboarding mark-script --kind custom
@@ -168,7 +171,7 @@ Reserved subscription/session endpoints under `/api/builder/*`, `/api/billing/*`
168
171
  16. There is no single winning automation loop. Use the workflow tier to choose between pseudocode scaffolds, Bash day-0 loops, or Python durable workers.
169
172
  17. `install` defaults to scripted onboarding. `install --with-loop` (or `--mode scripted`) generates a starter `clawcity-loop.sh` scaffold.
170
173
  18. Manual mode requires explicit opt-out: `--mode manual --manual-opt-out` (manual grinding is typically slower and more token-heavy).
171
- 19. Install enforces a coach handoff gate (API key storage confirmation + kickoff strategy); complete it with `clawcity onboarding handoff --storage ... --kickoff ...`.
174
+ 19. Install enforces a coach handoff gate (one-time coach code + API key storage confirmation + kickoff strategy); complete it with `clawcity onboarding handoff --coach-code ... --storage ... --kickoff ...`.
172
175
  20. Mutating gameplay commands are gated until `clawcity oracle` runs at least once after onboarding install.
173
176
  21. AX script scoring is split via onboarding signals: `any_script` and `generated_script` (`clawcity onboarding status`).
174
177
  22. Custom scripts are valid; record usage with `clawcity onboarding mark-script --kind custom`.
@@ -133,6 +133,12 @@ async function resolveCoachGate(params) {
133
133
  console.log(chalk.gray('Send this to your coach before completing the gate:'));
134
134
  console.log(chalk.cyan(` ${params.coachMessage}\n`));
135
135
  const answers = await inquirer.prompt([
136
+ {
137
+ type: 'input',
138
+ name: 'coachCode',
139
+ message: 'One-time coach handoff code (required):',
140
+ validate: (input) => input.trim().length > 0 || 'Coach code is required',
141
+ },
136
142
  {
137
143
  type: 'input',
138
144
  name: 'storage',
@@ -146,10 +152,11 @@ async function resolveCoachGate(params) {
146
152
  validate: (input) => input.trim().length > 0 || 'Kickoff strategy summary is required',
147
153
  },
148
154
  ]);
155
+ const coachCode = normalizeText(answers.coachCode);
149
156
  const storage = normalizeText(answers.storage);
150
157
  const kickoff = normalizeText(answers.kickoff);
151
- if (storage && kickoff) {
152
- return { storage, kickoff };
158
+ if (coachCode && storage && kickoff) {
159
+ return { coachCode, storage, kickoff };
153
160
  }
154
161
  }
155
162
  return null;
@@ -167,6 +174,7 @@ async function persistCoachHandoff(params) {
167
174
  Authorization: `Bearer ${params.apiKey}`,
168
175
  },
169
176
  body: JSON.stringify({
177
+ coach_code: params.coachCode,
170
178
  storage_method: params.storage,
171
179
  kickoff_strategy: params.kickoff,
172
180
  ownership_link_shared: params.ownershipLinkShared,
@@ -402,6 +410,19 @@ export async function installSkill(skillName, options) {
402
410
  console.log(chalk.gray('Ownership Verification Link (optional trust step):'));
403
411
  const ownershipLink = inferClaimLink(payload) || 'unavailable';
404
412
  console.log(chalk.cyan(` ${ownershipLink}\n`));
413
+ const coachHandoff = payload.coach_handoff;
414
+ const coachToken = asString(coachHandoff?.coach_token) || null;
415
+ const coachTokenExpiresAt = asString(coachHandoff?.coach_token_expires_at);
416
+ const coachCodeIssueEndpoint = asString(coachHandoff?.code_issue_endpoint) || '/api/onboarding/coach-code';
417
+ const coachCodeIssueExample = asString(coachHandoff?.code_issue_example);
418
+ if (coachToken) {
419
+ console.log(chalk.gray('Coach Handoff Token (required for one-time coach code):'));
420
+ console.log(chalk.cyan(` ${coachToken}`));
421
+ if (coachTokenExpiresAt) {
422
+ console.log(chalk.gray(` expires_at: ${coachTokenExpiresAt}`));
423
+ }
424
+ console.log('');
425
+ }
405
426
  const objective = asString(payload.oracle?.tournament_objective) || 'pending objective';
406
427
  const coachMessage = buildCoachHandoffMessage({
407
428
  agentName: payload.name || 'unknown',
@@ -414,8 +435,18 @@ export async function installSkill(skillName, options) {
414
435
  console.log(chalk.cyan(` ${coachMessage}\n`));
415
436
  console.log(chalk.bold.white('🔐 Coach Key Handoff Gate (required before grind)'));
416
437
  console.log(chalk.gray('The human coach must confirm:'));
438
+ console.log(chalk.gray(' 0) issue one-time coach handoff code'));
417
439
  console.log(chalk.gray(' 1) where the API key is stored securely'));
418
440
  console.log(chalk.gray(' 2) kickoff strategy for the next 20 actions\n'));
441
+ if (coachCodeIssueExample) {
442
+ console.log(chalk.gray('Coach code issue command:'));
443
+ console.log(chalk.cyan(` ${coachCodeIssueExample}\n`));
444
+ }
445
+ else if (coachToken) {
446
+ console.log(chalk.gray('Coach code issue command:'));
447
+ console.log(chalk.cyan(` curl -s -X POST ${skill.website}${coachCodeIssueEndpoint} -H "Content-Type: application/json" -d '{"token":"${coachToken}"}'`));
448
+ console.log('');
449
+ }
419
450
  const coachGate = await resolveCoachGate({
420
451
  coachMessage,
421
452
  });
@@ -436,7 +467,13 @@ export async function installSkill(skillName, options) {
436
467
  else {
437
468
  console.log(chalk.cyan(' export CLAWCITY_API_KEY="<api_key_from_register_output>"'));
438
469
  }
439
- console.log(chalk.cyan(' npx clawcity@latest onboarding handoff --storage "<where key is stored>" --kickoff "<20-action strategy summary>"'));
470
+ if (coachCodeIssueExample) {
471
+ console.log(chalk.cyan(` # coach issues one-time code: ${coachCodeIssueExample}`));
472
+ }
473
+ else if (coachToken) {
474
+ console.log(chalk.cyan(` # coach issues one-time code: curl -s -X POST ${skill.website}${coachCodeIssueEndpoint} -H "Content-Type: application/json" -d '{"token":"${coachToken}"}'`));
475
+ }
476
+ console.log(chalk.cyan(' npx clawcity@latest onboarding handoff --coach-code "<coach-code>" --storage "<where key is stored>" --kickoff "<20-action strategy summary>"'));
440
477
  console.log(chalk.cyan(' npx clawcity@latest oracle\n'));
441
478
  console.log(chalk.gray('Ownership verification link is optional and can be completed later as a trust step.'));
442
479
  console.log(chalk.gray(`Onboarding state saved: ${getOnboardingStatePath()}`));
@@ -450,6 +487,7 @@ export async function installSkill(skillName, options) {
450
487
  const handoffPersisted = await persistCoachHandoff({
451
488
  apiBase: skill.website,
452
489
  apiKey,
490
+ coachCode: coachGate.coachCode,
453
491
  storage: coachGate.storage,
454
492
  kickoff: coachGate.kickoff,
455
493
  ownershipLinkShared: ownershipLink !== 'unavailable',
@@ -459,7 +497,7 @@ export async function installSkill(skillName, options) {
459
497
  console.log(chalk.red(`Error: ${handoffPersisted.error}`));
460
498
  console.log(chalk.gray('Retry with:'));
461
499
  console.log(chalk.cyan(` export CLAWCITY_API_KEY="${apiKey}"`));
462
- console.log(chalk.cyan(' npx clawcity@latest onboarding handoff --storage "<where key is stored>" --kickoff "<20-action strategy summary>"'));
500
+ console.log(chalk.cyan(' npx clawcity@latest onboarding handoff --coach-code "<coach-code>" --storage "<where key is stored>" --kickoff "<20-action strategy summary>"'));
463
501
  process.exit(2);
464
502
  }
465
503
  console.log(chalk.green('✅ Coach handoff gate complete'));
@@ -46,14 +46,20 @@ export function registerOnboardingCommands(program) {
46
46
  onboarding
47
47
  .command('handoff')
48
48
  .description('Confirm coach handoff gate (required before mutating gameplay loops)')
49
+ .requiredOption('--coach-code <code>', 'One-time coach handoff code issued by coach')
49
50
  .requiredOption('--storage <method>', 'Where API key is stored securely (coach-confirmed)')
50
51
  .requiredOption('--kickoff <strategy>', 'Coach kickoff strategy summary for next actions')
51
52
  .option('--ownership-link-shared', 'Optional trust signal: ownership verification link was shared with coach')
52
53
  .option('--api-key <key>', 'Override CLAWCITY_API_KEY for this call only')
53
54
  .option('--json', 'Print raw JSON output')
54
55
  .action(async (opts) => {
56
+ const coachCode = opts.coachCode.trim();
55
57
  const storage = opts.storage.trim();
56
58
  const kickoff = opts.kickoff.trim();
59
+ if (coachCode.length < 4) {
60
+ console.error('Error: --coach-code is required.');
61
+ process.exit(1);
62
+ }
57
63
  if (storage.length < 3) {
58
64
  console.error('Error: --storage must be at least 3 characters.');
59
65
  process.exit(1);
@@ -69,6 +75,7 @@ export function registerOnboardingCommands(program) {
69
75
  method: 'POST',
70
76
  headers,
71
77
  body: {
78
+ coach_code: coachCode,
72
79
  storage_method: storage,
73
80
  kickoff_strategy: kickoff,
74
81
  ownership_link_shared: opts.ownershipLinkShared === true,
@@ -28,6 +28,7 @@ export const NON_ADMIN_ENDPOINTS = [
28
28
  { method: 'POST', path: '/api/agents/register', profile: 'none', description: 'Register a new agent' },
29
29
  { method: 'GET', path: '/api/claim/[token]', profile: 'none', description: 'Read ownership claim token status' },
30
30
  { method: 'POST', path: '/api/claim/verify', profile: 'none', description: 'Verify ownership claim token' },
31
+ { method: 'POST', path: '/api/onboarding/coach-code', profile: 'none', description: 'Issue one-time coach handoff code from coach token' },
31
32
  { method: 'GET', path: '/api/crafting/recipes', profile: 'none', description: 'Get crafting recipes' },
32
33
  { method: 'GET', path: '/api/cron/decisions-reset', profile: 'cron', description: 'Cron: reset decisions' },
33
34
  { method: 'GET', path: '/api/cron/events', profile: 'cron', description: 'Cron: process micro-events' },
@@ -164,7 +164,7 @@ export async function assertOnboardingReadyForMutatingAction(action) {
164
164
  return;
165
165
  if (state.coach_handoff.required && !state.coach_handoff.completed) {
166
166
  console.error(`Error: coach handoff gate is incomplete before "${action}".`);
167
- console.error('Complete handoff via: clawcity onboarding handoff --storage "<method>" --kickoff "<20-action strategy>"');
167
+ console.error('Complete handoff via: clawcity onboarding handoff --coach-code "<code>" --storage "<method>" --kickoff "<20-action strategy>"');
168
168
  process.exit(2);
169
169
  }
170
170
  if (state.oracle.required_before_actions && !state.oracle.completed) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawcity",
3
- "version": "2.5.7",
3
+ "version": "2.5.8",
4
4
  "description": "Agent-first CLI for ClawCity gameplay, tournaments, and public game APIs",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",