@ranger-testing/ranger-cli 1.1.7 → 2.0.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.
Files changed (90) hide show
  1. package/README.md +47 -45
  2. package/build/cli.js +644 -277
  3. package/build/cli.js.map +1 -1
  4. package/build/commands/addEnv.js +1 -1
  5. package/build/commands/addEnv.js.map +1 -1
  6. package/build/commands/authEncrypt.js +5 -10
  7. package/build/commands/authEncrypt.js.map +1 -1
  8. package/build/commands/clean.js +1 -1
  9. package/build/commands/clean.js.map +1 -1
  10. package/build/commands/config.js +9 -15
  11. package/build/commands/config.js.map +1 -1
  12. package/build/commands/env.js +10 -13
  13. package/build/commands/env.js.map +1 -1
  14. package/build/commands/feature.js +138 -67
  15. package/build/commands/feature.js.map +1 -1
  16. package/build/commands/hooks/autoPrompt.js +1 -1
  17. package/build/commands/hooks/disable.js +1 -1
  18. package/build/commands/hooks/enable.js +9 -4
  19. package/build/commands/hooks/enable.js.map +1 -1
  20. package/build/commands/hooks/exitPlanMode.js +8 -8
  21. package/build/commands/hooks/planReminder.js +7 -7
  22. package/build/commands/hooks/planStart.js +4 -4
  23. package/build/commands/hooks/postEdit.js +4 -4
  24. package/build/commands/hooks/postEdit.js.map +1 -1
  25. package/build/commands/hooks/preCompact.js +3 -3
  26. package/build/commands/hooks/preCompact.js.map +1 -1
  27. package/build/commands/hooks/sessionStart.js +19 -5
  28. package/build/commands/hooks/sessionStart.js.map +1 -1
  29. package/build/commands/hooks/stopHook.js +28 -4
  30. package/build/commands/hooks/stopHook.js.map +1 -1
  31. package/build/commands/index.js +1 -2
  32. package/build/commands/index.js.map +1 -1
  33. package/build/commands/login.js +2 -5
  34. package/build/commands/login.js.map +1 -1
  35. package/build/commands/setupCi.js +189 -0
  36. package/build/commands/setupCi.js.map +1 -0
  37. package/build/commands/skillup.js +16 -68
  38. package/build/commands/skillup.js.map +1 -1
  39. package/build/commands/start.js +1 -1
  40. package/build/commands/start.js.map +1 -1
  41. package/build/commands/status.js +14 -13
  42. package/build/commands/status.js.map +1 -1
  43. package/build/commands/update.js +34 -5
  44. package/build/commands/update.js.map +1 -1
  45. package/build/commands/updateEnv.js +1 -1
  46. package/build/commands/updateEnv.js.map +1 -1
  47. package/build/commands/useEnv.js +1 -1
  48. package/build/commands/useEnv.js.map +1 -1
  49. package/build/commands/utils/activeProfile.js +76 -0
  50. package/build/commands/utils/activeProfile.js.map +1 -0
  51. package/build/commands/utils/browserSessionsApi.js +1 -1
  52. package/build/commands/utils/browserSessionsApi.js.map +1 -1
  53. package/build/commands/utils/deviceAuth.js +53 -5
  54. package/build/commands/utils/deviceAuth.js.map +1 -1
  55. package/build/commands/utils/environment.js +11 -12
  56. package/build/commands/utils/environment.js.map +1 -1
  57. package/build/commands/utils/featureApi.js +30 -30
  58. package/build/commands/utils/featureApi.js.map +1 -1
  59. package/build/commands/utils/featureReportGenerator.js +6 -6
  60. package/build/commands/utils/featureReportGenerator.js.map +1 -1
  61. package/build/commands/utils/keychain.js +1 -1
  62. package/build/commands/utils/localAgentInstallationsApi.js +1 -1
  63. package/build/commands/utils/profileMessages.js +8 -0
  64. package/build/commands/utils/profileMessages.js.map +1 -0
  65. package/build/commands/utils/profileSetupBanner.js +167 -0
  66. package/build/commands/utils/profileSetupBanner.js.map +1 -0
  67. package/build/commands/utils/settings.js +20 -2
  68. package/build/commands/utils/settings.js.map +1 -1
  69. package/build/commands/utils/skills.js +1 -1
  70. package/build/commands/utils/telemetry.js +254 -0
  71. package/build/commands/utils/telemetry.js.map +1 -0
  72. package/build/commands/utils/userApi.js +4 -4
  73. package/build/commands/utils/userApi.js.map +1 -1
  74. package/build/commands/verifyFeature.js +771 -526
  75. package/build/commands/verifyFeature.js.map +1 -1
  76. package/build/commands/verifyInBrowser.js +1 -1
  77. package/build/commands/verifyInBrowser.js.map +1 -1
  78. package/build/skills/ranger/SKILL.md +65 -64
  79. package/build/skills/ranger/create.md +31 -31
  80. package/build/skills/ranger/feedback.md +25 -17
  81. package/build/skills/ranger/start.md +37 -37
  82. package/build/skills/ranger/verify.md +59 -55
  83. package/package.json +1 -1
  84. package/scripts/postinstall.js +1 -1
  85. package/build/commands/dataMcpServer.js +0 -1
  86. package/build/commands/dataMcpServer.js.map +0 -1
  87. package/build/commands/utils/cliSecret.js +0 -1
  88. package/build/commands/utils/cliSecret.js.map +0 -1
  89. package/build/skills/bug-bash.md +0 -329
  90. package/build/skills/e2e-test-recommender.md +0 -168
@@ -24,22 +24,22 @@ export async function planReminder(sessionIdOverride) {
24
24
  If this plan involves ANY UI changes, you MUST:
25
25
 
26
26
  1. **READ /ranger skill NOW** - specifically the create.md instructions
27
- 2. **Add a Ranger Feature Specification** to the end of your plan
27
+ 2. **Add a Ranger Feature Review Specification** to the end of your plan
28
28
 
29
- DO NOT write checklist items without reading create.md first.
30
- Checklist items are E2E test scenarios, NOT implementation tasks.
29
+ DO NOT write scenarios without reading create.md first.
30
+ Scenarios are E2E test flows, NOT implementation tasks.
31
31
 
32
32
  Your plan must end with:
33
33
  \`\`\`
34
- ### Ranger Feature Specification (create this first with \`ranger feature create\`)
35
- Feature Name: <name>
34
+ ### Ranger Feature Review Specification (create this first with \`ranger create\`)
35
+ Feature Review Name: <name>
36
36
  Description: <description>
37
- Checklist:
37
+ Scenarios:
38
38
  1. <E2E user flow that can be verified in browser>
39
39
  2. <another E2E user flow if needed>
40
40
  \`\`\`
41
41
 
42
- Then run: \`ranger feature create "<name>" -d "<desc>" -c "<item1>" -c "<item2>"\`
42
+ Then run: \`ranger create "<name>" -d "<desc>" -c "<scenario1>" -c "<scenario2>"\`
43
43
 
44
44
  === END ===`);
45
45
  }
@@ -3,7 +3,7 @@ import { printBlock, getEnabledSessionId } from './output.js';
3
3
  * SubagentStart hook handler for Plan mode
4
4
  *
5
5
  * This command is invoked when Claude enters plan mode (Plan subagent starts).
6
- * It reminds Claude to include Ranger checklist items as part of the planning process.
6
+ * It reminds Claude to include Ranger scenarios as part of the planning process.
7
7
  */
8
8
  export async function planStart(sessionIdOverride) {
9
9
  const sessionId = await getEnabledSessionId(sessionIdOverride);
@@ -15,15 +15,15 @@ export async function planStart(sessionIdOverride) {
15
15
  If this plan involves UI changes, you MUST:
16
16
 
17
17
  1. **READ /ranger skill** - specifically create.md
18
- 2. **Add a Ranger Feature Specification** at the end of your plan
18
+ 2. **Add a Ranger Feature Review Specification** at the end of your plan
19
19
 
20
- Checklist items are E2E test scenarios, NOT implementation tasks.
20
+ Scenarios are E2E test flows, NOT implementation tasks.
21
21
 
22
22
  **Good:** "User can log in with valid credentials and see dashboard"
23
23
  **Bad:** "Add form validation" or "Button is visible"
24
24
 
25
25
  After planning, run:
26
- \`ranger feature create "<name>" -d "<desc>" -c "<E2E flow 1>" -c "<E2E flow 2>"\`
26
+ \`ranger create "<name>" -d "<desc>" -c "<E2E flow 1>" -c "<E2E flow 2>"\`
27
27
 
28
28
  === END ===`);
29
29
  }
@@ -5,7 +5,7 @@ import { getEnabledSessionId } from './output.js';
5
5
  * PostToolUse (Write/Edit) hook handler for Claude Code plugin
6
6
  *
7
7
  * This command is invoked automatically after Write or Edit tools are used.
8
- * If the session isn't registered with a Ranger feature, prompts to use /ranger.
8
+ * If the session isn't registered with a Ranger feature review, prompts to use /ranger.
9
9
  */
10
10
  export async function postEdit(sessionIdOverride) {
11
11
  const sessionId = await getEnabledSessionId(sessionIdOverride);
@@ -21,11 +21,11 @@ export async function postEdit(sessionIdOverride) {
21
21
  // Check if this session is already registered
22
22
  const existingEntry = getSessionEntry(sessionId);
23
23
  if (existingEntry) {
24
- // Already registered - remind about adding checklist items if scope expanded
24
+ // Already registered - remind about adding scenarios if scope expanded
25
25
  const response = {
26
26
  hookSpecificOutput: {
27
27
  hookEventName: 'PostToolUse',
28
- additionalContext: `RANGER: If this change expands the scope of the active feature, you may need to add a checklist item. See Workflow 1 in /ranger. If you decide to add a checklist item, you MUST read Workflow 1 IN DETAIL first.`,
28
+ additionalContext: `RANGER: If this change expands the scope of the active feature review, you may need to add a scenario. See Workflow 1 in /ranger. If you decide to add a scenario, you MUST read Workflow 1 IN DETAIL first.`,
29
29
  },
30
30
  };
31
31
  console.log(JSON.stringify(response));
@@ -35,7 +35,7 @@ export async function postEdit(sessionIdOverride) {
35
35
  const response = {
36
36
  hookSpecificOutput: {
37
37
  hookEventName: 'PostToolUse',
38
- additionalContext: `RANGER: If this is for a UI feature, you MUST use /ranger to either create a new feature or resume an existing one.`,
38
+ additionalContext: `RANGER: If this is for a UI feature, you MUST use /ranger to either create a new feature review or resume an existing one.`,
39
39
  },
40
40
  };
41
41
  console.log(JSON.stringify(response));
@@ -1 +1 @@
1
- {"version":3,"file":"postEdit.js","sourceRoot":"","sources":["../../../src/commands/hooks/postEdit.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,eAAe,EACf,oBAAoB,GACvB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAElD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,iBAA0B;IACrD,MAAM,SAAS,GAAG,MAAM,mBAAmB,CAAC,iBAAiB,CAAC,CAAC;IAC/D,IAAI,CAAC,SAAS,EAAE,CAAC;QACb,OAAO;IACX,CAAC;IAED,sFAAsF;IACtF,oBAAoB,CAAC,SAAS,CAAC,CAAC;IAEhC,MAAM,KAAK,GAAG,MAAM,QAAQ,EAAE,CAAC;IAC/B,IAAI,CAAC,KAAK,EAAE,CAAC;QACT,OAAO;IACX,CAAC;IAED,8CAA8C;IAC9C,MAAM,aAAa,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;IACjD,IAAI,aAAa,EAAE,CAAC;QAChB,6EAA6E;QAC7E,MAAM,QAAQ,GAAG;YACb,kBAAkB,EAAE;gBAChB,aAAa,EAAE,aAAa;gBAC5B,iBAAiB,EAAE,mNAAmN;aACzO;SACJ,CAAC;QACF,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;QACtC,OAAO;IACX,CAAC;IAED,qDAAqD;IACrD,MAAM,QAAQ,GAAG;QACb,kBAAkB,EAAE;YAChB,aAAa,EAAE,aAAa;YAC5B,iBAAiB,EAAE,qHAAqH;SAC3I;KACJ,CAAC;IACF,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;AAC1C,CAAC"}
1
+ {"version":3,"file":"postEdit.js","sourceRoot":"","sources":["../../../src/commands/hooks/postEdit.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,eAAe,EACf,oBAAoB,GACvB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAElD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,iBAA0B;IACrD,MAAM,SAAS,GAAG,MAAM,mBAAmB,CAAC,iBAAiB,CAAC,CAAC;IAC/D,IAAI,CAAC,SAAS,EAAE,CAAC;QACb,OAAO;IACX,CAAC;IAED,sFAAsF;IACtF,oBAAoB,CAAC,SAAS,CAAC,CAAC;IAEhC,MAAM,KAAK,GAAG,MAAM,QAAQ,EAAE,CAAC;IAC/B,IAAI,CAAC,KAAK,EAAE,CAAC;QACT,OAAO;IACX,CAAC;IAED,8CAA8C;IAC9C,MAAM,aAAa,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;IACjD,IAAI,aAAa,EAAE,CAAC;QAChB,uEAAuE;QACvE,MAAM,QAAQ,GAAG;YACb,kBAAkB,EAAE;gBAChB,aAAa,EAAE,aAAa;gBAC5B,iBAAiB,EAAE,8MAA8M;aACpO;SACJ,CAAC;QACF,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;QACtC,OAAO;IACX,CAAC;IAED,qDAAqD;IACrD,MAAM,QAAQ,GAAG;QACb,kBAAkB,EAAE;YAChB,aAAa,EAAE,aAAa;YAC5B,iBAAiB,EAAE,4HAA4H;SAClJ;KACJ,CAAC;IACF,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;AAC1C,CAAC"}
@@ -4,7 +4,7 @@ import { printBlock, getEnabledSessionId } from './output.js';
4
4
  * PreCompact hook handler for Claude Code plugin
5
5
  *
6
6
  * This command is invoked automatically before Claude Code compacts the conversation.
7
- * It reminds Claude to preserve Ranger Feature Specification in the compaction summary.
7
+ * It reminds Claude to preserve Ranger Feature Review Specification in the compaction summary.
8
8
  */
9
9
  export async function preCompact(sessionIdOverride) {
10
10
  const sessionId = await getEnabledSessionId(sessionIdOverride);
@@ -19,9 +19,9 @@ export async function preCompact(sessionIdOverride) {
19
19
  }
20
20
  printBlock(`=== RANGER: PRESERVE IN COMPACTION ===
21
21
 
22
- If you created a plan with a **Ranger Feature Specification**, you MUST preserve it in the compaction summary.
22
+ If you created a plan with a **Ranger Feature Review Specification**, you MUST preserve it in the compaction summary.
23
23
 
24
- The specification contains checklist items that will be used with \`ranger feature create\`.`);
24
+ The specification contains scenarios that will be used with \`ranger create\`.`);
25
25
  }
26
26
  catch {
27
27
  // Silently fail - don't interrupt compaction
@@ -1 +1 @@
1
- {"version":3,"file":"preCompact.js","sourceRoot":"","sources":["../../../src/commands/hooks/preCompact.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAE9D;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,iBAA0B;IACvD,MAAM,SAAS,GAAG,MAAM,mBAAmB,CAAC,iBAAiB,CAAC,CAAC;IAC/D,IAAI,CAAC,SAAS,EAAE,CAAC;QACb,OAAO;IACX,CAAC;IAED,IAAI,CAAC;QACD,gCAAgC;QAChC,MAAM,KAAK,GAAG,MAAM,QAAQ,EAAE,CAAC;QAC/B,IAAI,CAAC,KAAK,EAAE,CAAC;YACT,OAAO;QACX,CAAC;QAED,UAAU,CAAC;;;;6FAI0E,CAAC,CAAC;IAC3F,CAAC;IAAC,MAAM,CAAC;QACL,6CAA6C;IACjD,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"preCompact.js","sourceRoot":"","sources":["../../../src/commands/hooks/preCompact.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAE9D;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,iBAA0B;IACvD,MAAM,SAAS,GAAG,MAAM,mBAAmB,CAAC,iBAAiB,CAAC,CAAC;IAC/D,IAAI,CAAC,SAAS,EAAE,CAAC;QACb,OAAO;IACX,CAAC;IAED,IAAI,CAAC;QACD,gCAAgC;QAChC,MAAM,KAAK,GAAG,MAAM,QAAQ,EAAE,CAAC;QAC/B,IAAI,CAAC,KAAK,EAAE,CAAC;YACT,OAAO;QACX,CAAC;QAED,UAAU,CAAC;;;;+EAI4D,CAAC,CAAC;IAC7E,CAAC;IAAC,MAAM,CAAC;QACL,6CAA6C;IACjD,CAAC;AACL,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import { appendFile } from 'fs/promises';
2
2
  import { initBranchTracking, shouldAutoEnableAfterClear, autoEnableAfterClear, isSessionEnabled, getCurrentBranch, } from '../utils/sessionCache.js';
3
+ import { createTelemetryCollector } from '../utils/telemetry.js';
3
4
  const RANGER_AUTO_ENABLED_PROMPT = `=================================================================
4
5
  🚨 RANGER IS ACTIVE 🚨
5
6
  =================================================================
@@ -8,13 +9,13 @@ This session has Ranger ENABLED. Before doing ANYTHING else:
8
9
 
9
10
  1. **READ the /ranger skill FIRST** - Run the skill to understand the required workflow for UI features
10
11
 
11
- 2. **Check for existing features** - Run \`ranger feature list\` to see if there's an in-progress feature to resume
12
+ 2. **Check for existing feature reviews** - Run \`ranger list\` to see if there's an in-progress feature review to resume
12
13
 
13
14
  3. **For ANY UI work**: You MUST either:
14
- - Resume an existing feature: \`ranger feature resume <id>\`
15
- - Create a new feature: \`ranger feature create "<name>" -d "<desc>" -c "<checklist item>"\`
15
+ - Resume an existing feature review: \`ranger resume <id>\`
16
+ - Create a new feature review: \`ranger create "<name>" -d "<desc>" -c "<scenario>"\`
16
17
 
17
- 4. **If resuming a feature with reviewer comments**: Run \`ranger feature get-feedback\` to see what reviewers want fixed before making code changes
18
+ 4. **If resuming a feature review with reviewer comments**: Run \`ranger get-review\` to see what reviewers want fixed before making code changes
18
19
 
19
20
  =================================================================`;
20
21
  /**
@@ -60,8 +61,21 @@ export async function sessionStart(sessionIdOverride) {
60
61
  }
61
62
  // Initialize branch tracking - auto-enable session if branch is already enabled
62
63
  initBranchTracking(sessionId);
64
+ const enabled = isSessionEnabled(sessionId);
65
+ // Telemetry: log session start with enabled status
66
+ try {
67
+ const telemetry = createTelemetryCollector('hook:session-start');
68
+ await telemetry.trackCommandStart({
69
+ sessionId,
70
+ hooksEnabled: enabled,
71
+ });
72
+ await telemetry.trackCommandEnd('success');
73
+ }
74
+ catch {
75
+ // Telemetry must never throw
76
+ }
63
77
  // If session is now enabled (via branch or clear), output strong prompting
64
- if (isSessionEnabled(sessionId)) {
78
+ if (enabled) {
65
79
  const branch = getCurrentBranch();
66
80
  const branchInfo = branch && branch !== 'main' && branch !== 'master'
67
81
  ? ` (Branch: ${branch})`
@@ -1 +1 @@
1
- {"version":3,"file":"sessionStart.js","sourceRoot":"","sources":["../../../src/commands/hooks/sessionStart.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EACH,kBAAkB,EAClB,0BAA0B,EAC1B,oBAAoB,EACpB,gBAAgB,EAChB,gBAAgB,GACnB,MAAM,0BAA0B,CAAC;AAElC,MAAM,0BAA0B,GAAG;;;;;;;;;;;;;;;;kEAgB+B,CAAC;AAEnE;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,iBAA0B;IACzD,IAAI,SAAS,GAAG,iBAAiB,IAAI,EAAE,CAAC;IACxC,IAAI,MAA0B,CAAC;IAE/B,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACrB,4EAA4E;QAC5E,IAAI,KAAK,GAAG,EAAE,CAAC;QACf,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YACtC,KAAK,IAAI,KAAK,CAAC;QACnB,CAAC;QAED,IAAI,CAAC;YACD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC/B,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;YACrC,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC5B,CAAC;QAAC,MAAM,CAAC;YACL,sBAAsB;QAC1B,CAAC;QAED,uEAAuE;QACvE,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;QAC5C,IAAI,OAAO,IAAI,SAAS,EAAE,CAAC;YACvB,IAAI,CAAC;gBACD,MAAM,UAAU,CACZ,OAAO,EACP,6BAA6B,SAAS,KAAK,CAC9C,CAAC;YACN,CAAC;YAAC,MAAM,CAAC;gBACL,oCAAoC;YACxC,CAAC;QACL,CAAC;IACL,CAAC;IAED,IAAI,SAAS,EAAE,CAAC;QACZ,mFAAmF;QACnF,IAAI,0BAA0B,CAAC,MAAM,CAAC,EAAE,CAAC;YACrC,oBAAoB,CAAC,SAAS,CAAC,CAAC;QACpC,CAAC;QAED,gFAAgF;QAChF,kBAAkB,CAAC,SAAS,CAAC,CAAC;QAE9B,2EAA2E;QAC3E,IAAI,gBAAgB,CAAC,SAAS,CAAC,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,gBAAgB,EAAE,CAAC;YAClC,MAAM,UAAU,GACZ,MAAM,IAAI,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,QAAQ;gBAC9C,CAAC,CAAC,aAAa,MAAM,GAAG;gBACxB,CAAC,CAAC,EAAE,CAAC;YAEb,MAAM,QAAQ,GAAG;gBACb,kBAAkB,EAAE;oBAChB,aAAa,EAAE,cAAc;oBAC7B,iBAAiB,EAAE,0BAA0B,GAAG,UAAU;iBAC7D;aACJ,CAAC;YACF,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC1C,CAAC;IACL,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"sessionStart.js","sourceRoot":"","sources":["../../../src/commands/hooks/sessionStart.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EACH,kBAAkB,EAClB,0BAA0B,EAC1B,oBAAoB,EACpB,gBAAgB,EAChB,gBAAgB,GACnB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAEjE,MAAM,0BAA0B,GAAG;;;;;;;;;;;;;;;;kEAgB+B,CAAC;AAEnE;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,iBAA0B;IACzD,IAAI,SAAS,GAAG,iBAAiB,IAAI,EAAE,CAAC;IACxC,IAAI,MAA0B,CAAC;IAE/B,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACrB,4EAA4E;QAC5E,IAAI,KAAK,GAAG,EAAE,CAAC;QACf,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YACtC,KAAK,IAAI,KAAK,CAAC;QACnB,CAAC;QAED,IAAI,CAAC;YACD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC/B,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;YACrC,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC5B,CAAC;QAAC,MAAM,CAAC;YACL,sBAAsB;QAC1B,CAAC;QAED,uEAAuE;QACvE,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;QAC5C,IAAI,OAAO,IAAI,SAAS,EAAE,CAAC;YACvB,IAAI,CAAC;gBACD,MAAM,UAAU,CACZ,OAAO,EACP,6BAA6B,SAAS,KAAK,CAC9C,CAAC;YACN,CAAC;YAAC,MAAM,CAAC;gBACL,oCAAoC;YACxC,CAAC;QACL,CAAC;IACL,CAAC;IAED,IAAI,SAAS,EAAE,CAAC;QACZ,mFAAmF;QACnF,IAAI,0BAA0B,CAAC,MAAM,CAAC,EAAE,CAAC;YACrC,oBAAoB,CAAC,SAAS,CAAC,CAAC;QACpC,CAAC;QAED,gFAAgF;QAChF,kBAAkB,CAAC,SAAS,CAAC,CAAC;QAE9B,MAAM,OAAO,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;QAE5C,mDAAmD;QACnD,IAAI,CAAC;YACD,MAAM,SAAS,GAAG,wBAAwB,CAAC,oBAAoB,CAAC,CAAC;YACjE,MAAM,SAAS,CAAC,iBAAiB,CAAC;gBAC9B,SAAS;gBACT,YAAY,EAAE,OAAO;aACxB,CAAC,CAAC;YACH,MAAM,SAAS,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;QAC/C,CAAC;QAAC,MAAM,CAAC;YACL,6BAA6B;QACjC,CAAC;QAED,2EAA2E;QAC3E,IAAI,OAAO,EAAE,CAAC;YACV,MAAM,MAAM,GAAG,gBAAgB,EAAE,CAAC;YAClC,MAAM,UAAU,GACZ,MAAM,IAAI,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,QAAQ;gBAC9C,CAAC,CAAC,aAAa,MAAM,GAAG;gBACxB,CAAC,CAAC,EAAE,CAAC;YAEb,MAAM,QAAQ,GAAG;gBACb,kBAAkB,EAAE;oBAChB,aAAa,EAAE,cAAc;oBAC7B,iBAAiB,EAAE,0BAA0B,GAAG,UAAU;iBAC7D;aACJ,CAAC;YACF,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC1C,CAAC;IACL,CAAC;AACL,CAAC"}
@@ -2,53 +2,77 @@ import { getToken } from '../utils/keychain.js';
2
2
  import { getFeature, concludeSession } from '../utils/featureApi.js';
3
3
  import { getSessionEntry } from '../utils/sessionCache.js';
4
4
  import { getEnabledSessionId } from './output.js';
5
+ import { createTelemetryCollector } from '../utils/telemetry.js';
5
6
  /**
6
7
  * Stop hook handler
7
8
  *
8
- * Only blocks stop for Claude sessions that have registered with a Ranger feature.
9
- * Attempts to conclude the feature session before allowing stop.
9
+ * Only blocks stop for Claude sessions that have registered with a Ranger feature review.
10
+ * Attempts to conclude the feature review session before allowing stop.
10
11
  */
11
12
  export async function stopHook(sessionIdOverride) {
12
13
  const sessionId = await getEnabledSessionId(sessionIdOverride);
14
+ let stopAllowed = true;
13
15
  if (!sessionId) {
16
+ await trackStop(sessionId, false, stopAllowed);
14
17
  return;
15
18
  }
16
19
  try {
17
- // Check if this Claude session is registered with a Ranger feature
20
+ // Check if this Claude session is registered with a Ranger feature review
18
21
  const sessionEntry = getSessionEntry(sessionId);
19
22
  if (!sessionEntry) {
20
23
  // Not a Ranger session - allow stop
24
+ await trackStop(sessionId, true, stopAllowed);
21
25
  return;
22
26
  }
23
27
  const token = await getToken();
24
28
  if (!token) {
25
29
  // No token configured - allow stop
30
+ await trackStop(sessionId, true, stopAllowed);
26
31
  return;
27
32
  }
28
33
  // Get the feature
29
34
  const feature = await getFeature(sessionEntry.featureId);
30
35
  // If there's no current session, allow stop
31
36
  if (!feature.currentSessionId) {
37
+ await trackStop(sessionId, true, stopAllowed);
32
38
  return;
33
39
  }
34
40
  // Try to conclude the session
35
41
  try {
36
42
  await concludeSession(feature.id, feature.currentSessionId);
43
+ await trackStop(sessionId, true, stopAllowed);
37
44
  return;
38
45
  }
39
46
  catch (err) {
40
47
  // Failed to conclude - block with error message
48
+ stopAllowed = false;
41
49
  const errorMessage = err instanceof Error ? err.message : String(err);
42
50
  const output = {
43
51
  decision: 'block',
44
- reason: `Failed to conclude Ranger feature session for "${feature.name}":\n\n${errorMessage}\n\n. This is most likely due to pending checklist items that need to be attempted to be verified. Please resolve the issue or manually conclude with:\n ranger feature conclude-session`,
52
+ reason: `Failed to conclude Ranger feature review session for "${feature.name}":\n\n${errorMessage}\n\nThis is most likely due to pending scenarios that need to be verified. Please resolve the issue or resume later with:\n ranger resume`,
45
53
  };
46
54
  console.log(JSON.stringify(output));
55
+ await trackStop(sessionId, true, stopAllowed);
47
56
  }
48
57
  }
49
58
  catch {
50
59
  // On any error fetching feature, allow stop (fail open)
60
+ await trackStop(sessionId, true, stopAllowed);
51
61
  return;
52
62
  }
53
63
  }
64
+ async function trackStop(sessionId, hooksEnabled, stopAllowed) {
65
+ try {
66
+ const telemetry = createTelemetryCollector('hook:stop');
67
+ await telemetry.trackCommandStart({
68
+ sessionId: sessionId ?? undefined,
69
+ hooksEnabled,
70
+ stopAllowed,
71
+ });
72
+ await telemetry.trackCommandEnd('success');
73
+ }
74
+ catch {
75
+ // Telemetry must never throw
76
+ }
77
+ }
54
78
  //# sourceMappingURL=stopHook.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"stopHook.js","sourceRoot":"","sources":["../../../src/commands/hooks/stopHook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAElD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,iBAA0B;IACrD,MAAM,SAAS,GAAG,MAAM,mBAAmB,CAAC,iBAAiB,CAAC,CAAC;IAC/D,IAAI,CAAC,SAAS,EAAE,CAAC;QACb,OAAO;IACX,CAAC;IAED,IAAI,CAAC;QACD,mEAAmE;QACnE,MAAM,YAAY,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;QAChD,IAAI,CAAC,YAAY,EAAE,CAAC;YAChB,oCAAoC;YACpC,OAAO;QACX,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,QAAQ,EAAE,CAAC;QAC/B,IAAI,CAAC,KAAK,EAAE,CAAC;YACT,mCAAmC;YACnC,OAAO;QACX,CAAC;QAED,kBAAkB;QAClB,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;QAEzD,4CAA4C;QAC5C,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC;YAC5B,OAAO;QACX,CAAC;QAED,8BAA8B;QAC9B,IAAI,CAAC;YACD,MAAM,eAAe,CAAC,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;YAC5D,OAAO;QACX,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACX,gDAAgD;YAChD,MAAM,YAAY,GACd,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACrD,MAAM,MAAM,GAAG;gBACX,QAAQ,EAAE,OAAO;gBACjB,MAAM,EAAE,kDAAkD,OAAO,CAAC,IAAI,SAAS,YAAY,2LAA2L;aACzR,CAAC;YACF,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;QACxC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACL,wDAAwD;QACxD,OAAO;IACX,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"stopHook.js","sourceRoot":"","sources":["../../../src/commands/hooks/stopHook.ts"],"names":[],"mappings":"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"}
@@ -1,13 +1,12 @@
1
1
  export { addEnv } from './addEnv.js';
2
2
  export { clean } from './clean.js';
3
- export { dataMcpServer } from './dataMcpServer.js';
4
3
  export { login } from './login.js';
5
4
  export { start } from './start.js';
6
5
  export { useEnv } from './useEnv.js';
7
6
  export { updateEnv } from './updateEnv.js';
8
- export { verifyInBrowser } from './verifyInBrowser.js';
9
7
  export { update } from './update.js';
10
8
  export { skillup } from './skillup.js';
11
9
  export { envList } from './env.js';
12
10
  export { hook } from './hook.js';
11
+ export { setupCi } from './setupCi.js';
13
12
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACnC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACnC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC"}
@@ -7,9 +7,7 @@ import { getCurrentUser } from './utils/userApi.js';
7
7
  export async function login() {
8
8
  const isInteractive = process.stdin.isTTY && process.stdout.isTTY;
9
9
  if (!isInteractive) {
10
- console.error('Login requires an interactive terminal.');
11
- console.error('In CI, use: ranger start <token> or set RANGER_MCP_TOKEN.');
12
- process.exit(1);
10
+ throw new Error('Login requires an interactive terminal. In CI, use: ranger setup [token] or set RANGER_MCP_TOKEN.');
13
11
  }
14
12
  try {
15
13
  const token = await runDeviceAuthFlow();
@@ -22,8 +20,7 @@ export async function login() {
22
20
  }
23
21
  }
24
22
  catch (error) {
25
- console.error(`\n❌ Login failed: ${error instanceof Error ? error.message : error}`);
26
- process.exit(1);
23
+ throw new Error(`Login failed: ${error instanceof Error ? error.message : error}`);
27
24
  }
28
25
  }
29
26
  //# sourceMappingURL=login.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK;IACvB,MAAM,aAAa,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC;IAClE,IAAI,CAAC,aAAa,EAAE,CAAC;QACjB,OAAO,CAAC,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC3D,OAAO,CAAC,KAAK,CACT,2DAA2D,CAC9D,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;IAED,IAAI,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,iBAAiB,EAAE,CAAC;QAExC,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,KAAK,CAAC,CAAC;QAC3C,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,OAAO,CAAC,GAAG,CAAC,oBAAoB,MAAM,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC;QACpE,CAAC;aAAM,CAAC;YACJ,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;QACnD,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CACT,qBAAqB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE,CACxE,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK;IACvB,MAAM,aAAa,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC;IAClE,IAAI,CAAC,aAAa,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CACX,mGAAmG,CACtG,CAAC;IACN,CAAC;IAED,IAAI,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,iBAAiB,EAAE,CAAC;QAExC,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,KAAK,CAAC,CAAC;QAC3C,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,OAAO,CAAC,GAAG,CAAC,oBAAoB,MAAM,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC;QACpE,CAAC;aAAM,CAAC;YACJ,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;QACnD,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACX,iBAAiB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE,CACpE,CAAC;IACN,CAAC;AACL,CAAC"}
@@ -0,0 +1,189 @@
1
+ import { mkdir, readFile, readdir } from 'fs/promises';
2
+ import { join } from 'path';
3
+ import { existsSync } from 'fs';
4
+ import { authenticate, ensureRangerDir, ensureChromium, writeRangerGitignore, } from './start.js';
5
+ import { skillup } from './skillup.js';
6
+ import { getRangerDir } from './utils/rangerRoot.js';
7
+ import { writeActiveProfileName } from './utils/activeProfile.js';
8
+ import { saveSettings } from './utils/settings.js';
9
+ import { decrypt } from './utils/crypto.js';
10
+ import { getToken } from './utils/keychain.js';
11
+ import { runClaudeCommand, isMarketplaceAdded, isPluginInstalled, } from './utils/claudePlugin.js';
12
+ /**
13
+ * Find a CI profile to activate.
14
+ * If profileName is specified, use it. Otherwise auto-detect from .ranger/ci/.
15
+ */
16
+ async function findCiProfile(profileName) {
17
+ const rangerDir = getRangerDir();
18
+ const ciDir = join(rangerDir, 'ci');
19
+ if (profileName) {
20
+ const profilePath = join(ciDir, profileName);
21
+ // Profile may not exist yet if --base-url will create it
22
+ return { name: profileName, path: profilePath };
23
+ }
24
+ // Auto-detect: scan .ranger/ci/ for directories
25
+ if (!existsSync(ciDir)) {
26
+ throw new Error('No CI profiles found. Create one first with: ranger profile add <name> --ci\n' +
27
+ 'Or specify a profile name with --profile and --base-url to create one.');
28
+ }
29
+ const entries = await readdir(ciDir, { withFileTypes: true });
30
+ const profiles = entries.filter((e) => e.isDirectory()).map((e) => e.name);
31
+ if (profiles.length === 0) {
32
+ throw new Error('No CI profiles found in .ranger/ci/. Create one first with: ranger profile add <name> --ci\n' +
33
+ 'Or specify a profile name with --profile and --base-url to create one.');
34
+ }
35
+ if (profiles.length === 1) {
36
+ const name = profiles[0];
37
+ console.log(`Auto-detected CI profile: ${name}`);
38
+ return { name, path: join(ciDir, name) };
39
+ }
40
+ // Multiple profiles — require --profile flag
41
+ throw new Error(`Multiple CI profiles found: ${profiles.join(', ')}. Use --profile to specify which one.`);
42
+ }
43
+ /**
44
+ * Install Claude Code plugin at project scope (non-interactive).
45
+ */
46
+ async function installPluginNonInteractive() {
47
+ const alreadyInstalled = await isPluginInstalled('ranger@trailhead');
48
+ if (alreadyInstalled) {
49
+ console.log('✓ Claude Code plugin already installed');
50
+ return false;
51
+ }
52
+ console.log('Installing Claude Code plugin (project level)...');
53
+ const marketplaceAlreadyAdded = await isMarketplaceAdded('trailhead');
54
+ let marketplaceReady = marketplaceAlreadyAdded;
55
+ if (marketplaceAlreadyAdded) {
56
+ console.log('✓ Marketplace already added');
57
+ }
58
+ else {
59
+ const result = await runClaudeCommand([
60
+ 'plugin',
61
+ 'marketplace',
62
+ 'add',
63
+ 'ranger-testing/trailhead',
64
+ ]);
65
+ if (!result.success) {
66
+ console.error('Failed to add marketplace:', result.error);
67
+ console.log('You can install manually: claude plugin marketplace add ranger-testing/trailhead');
68
+ }
69
+ else {
70
+ marketplaceReady = true;
71
+ }
72
+ }
73
+ if (marketplaceReady) {
74
+ const result = await runClaudeCommand([
75
+ 'plugin',
76
+ 'install',
77
+ 'ranger@trailhead',
78
+ '--scope',
79
+ 'project',
80
+ ]);
81
+ if (!result.success) {
82
+ console.error('Failed to install plugin:', result.error);
83
+ console.log('You can install manually: claude plugin install ranger@trailhead --scope project');
84
+ }
85
+ else {
86
+ console.log('✓ Claude Code plugin installed');
87
+ }
88
+ }
89
+ return true;
90
+ }
91
+ /**
92
+ * Non-interactive CI setup. Authenticates, installs Chromium, activates a CI profile,
93
+ * installs plugin and skills — all without prompts.
94
+ */
95
+ export async function setupCi(token, options, telemetry) {
96
+ console.log('\n🔧 Ranger CI Setup\n');
97
+ // Phase 1: Auth
98
+ telemetry?.trackPhaseStart('auth');
99
+ await authenticate(token);
100
+ telemetry?.trackPhaseEnd('auth');
101
+ // Phase 2: .ranger/ directory
102
+ telemetry?.trackPhaseStart('dir_setup');
103
+ const { path: rangerDir, installed: dirCreated } = await ensureRangerDir();
104
+ await writeRangerGitignore(rangerDir);
105
+ // Ensure sessions directory exists
106
+ const sessionsDir = join(rangerDir, 'sessions');
107
+ if (!existsSync(sessionsDir)) {
108
+ await mkdir(sessionsDir, { recursive: true });
109
+ }
110
+ telemetry?.trackPhaseEnd('dir_setup', { installed: dirCreated });
111
+ // Phase 3: Chromium
112
+ telemetry?.trackPhaseStart('chromium');
113
+ let chromiumInstalled = false;
114
+ if (options?.skipChromium) {
115
+ console.log('✓ Skipping Chromium check (--skip-chromium)');
116
+ }
117
+ else {
118
+ chromiumInstalled = await ensureChromium();
119
+ }
120
+ telemetry?.trackPhaseEnd('chromium', {
121
+ installed: chromiumInstalled,
122
+ skipped: !!options?.skipChromium,
123
+ });
124
+ // Phase 4: Profile activation
125
+ telemetry?.trackPhaseStart('profile_activate');
126
+ const profile = await findCiProfile(options?.profile);
127
+ // Create/update settings if --base-url provided
128
+ let createdSettings = false;
129
+ if (options?.baseUrl) {
130
+ await mkdir(profile.path, { recursive: true });
131
+ await saveSettings(profile.name, {
132
+ baseUrl: options.baseUrl,
133
+ headless: true,
134
+ });
135
+ console.log(`✓ Created profile settings: baseUrl=${options.baseUrl}`);
136
+ createdSettings = true;
137
+ }
138
+ // Verify profile has settings
139
+ const settingsPath = join(profile.path, 'settings.json');
140
+ if (!existsSync(settingsPath) && !createdSettings) {
141
+ throw new Error(`CI profile "${profile.name}" has no settings.json. Use --base-url to configure it.`);
142
+ }
143
+ // Check auth state
144
+ const authPath = join(profile.path, 'auth.json');
145
+ const encryptedAuthPath = join(profile.path, 'auth.json.enc');
146
+ const hasAuth = existsSync(authPath);
147
+ const hasEncryptedAuth = existsSync(encryptedAuthPath);
148
+ if (hasEncryptedAuth) {
149
+ // Verify we can decrypt it
150
+ try {
151
+ const apiToken = await getToken();
152
+ if (!apiToken) {
153
+ throw new Error('No API token available for decryption');
154
+ }
155
+ const encrypted = await readFile(encryptedAuthPath);
156
+ decrypt(encrypted, apiToken);
157
+ console.log('✓ Encrypted auth verified (will decrypt at runtime)');
158
+ }
159
+ catch (error) {
160
+ const msg = error instanceof Error ? error.message : String(error);
161
+ throw new Error(`Failed to verify encrypted auth for profile "${profile.name}": ${msg}`);
162
+ }
163
+ }
164
+ else if (hasAuth) {
165
+ console.log('✓ Auth state found');
166
+ }
167
+ else {
168
+ console.log(' No auth state found (app may not require authentication)');
169
+ }
170
+ // Set as active profile
171
+ await writeActiveProfileName(profile.name);
172
+ console.log(`✓ Active profile: ${profile.name}`);
173
+ telemetry?.trackPhaseEnd('profile_activate', {
174
+ profileName: profile.name,
175
+ hasAuth,
176
+ hasEncryptedAuth,
177
+ createdSettings,
178
+ });
179
+ // Phase 5: Plugin
180
+ telemetry?.trackPhaseStart('plugin');
181
+ const pluginInstalled = await installPluginNonInteractive();
182
+ telemetry?.trackPhaseEnd('plugin', { installed: pluginInstalled });
183
+ // Phase 6: Skills
184
+ telemetry?.trackPhaseStart('skills');
185
+ await skillup({ autoInstall: 'project' });
186
+ telemetry?.trackPhaseEnd('skills');
187
+ console.log('\n✅ Ranger CI setup complete!\n');
188
+ }
189
+ //# sourceMappingURL=setupCi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setupCi.js","sourceRoot":"","sources":["../../src/commands/setupCi.ts"],"names":[],"mappings":"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"}