@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.
- package/README.md +47 -45
- package/build/cli.js +644 -277
- package/build/cli.js.map +1 -1
- package/build/commands/addEnv.js +1 -1
- package/build/commands/addEnv.js.map +1 -1
- package/build/commands/authEncrypt.js +5 -10
- package/build/commands/authEncrypt.js.map +1 -1
- package/build/commands/clean.js +1 -1
- package/build/commands/clean.js.map +1 -1
- package/build/commands/config.js +9 -15
- package/build/commands/config.js.map +1 -1
- package/build/commands/env.js +10 -13
- package/build/commands/env.js.map +1 -1
- package/build/commands/feature.js +138 -67
- package/build/commands/feature.js.map +1 -1
- package/build/commands/hooks/autoPrompt.js +1 -1
- package/build/commands/hooks/disable.js +1 -1
- package/build/commands/hooks/enable.js +9 -4
- package/build/commands/hooks/enable.js.map +1 -1
- package/build/commands/hooks/exitPlanMode.js +8 -8
- package/build/commands/hooks/planReminder.js +7 -7
- package/build/commands/hooks/planStart.js +4 -4
- package/build/commands/hooks/postEdit.js +4 -4
- package/build/commands/hooks/postEdit.js.map +1 -1
- package/build/commands/hooks/preCompact.js +3 -3
- package/build/commands/hooks/preCompact.js.map +1 -1
- package/build/commands/hooks/sessionStart.js +19 -5
- package/build/commands/hooks/sessionStart.js.map +1 -1
- package/build/commands/hooks/stopHook.js +28 -4
- package/build/commands/hooks/stopHook.js.map +1 -1
- package/build/commands/index.js +1 -2
- package/build/commands/index.js.map +1 -1
- package/build/commands/login.js +2 -5
- package/build/commands/login.js.map +1 -1
- package/build/commands/setupCi.js +189 -0
- package/build/commands/setupCi.js.map +1 -0
- package/build/commands/skillup.js +16 -68
- package/build/commands/skillup.js.map +1 -1
- package/build/commands/start.js +1 -1
- package/build/commands/start.js.map +1 -1
- package/build/commands/status.js +14 -13
- package/build/commands/status.js.map +1 -1
- package/build/commands/update.js +34 -5
- package/build/commands/update.js.map +1 -1
- package/build/commands/updateEnv.js +1 -1
- package/build/commands/updateEnv.js.map +1 -1
- package/build/commands/useEnv.js +1 -1
- package/build/commands/useEnv.js.map +1 -1
- package/build/commands/utils/activeProfile.js +76 -0
- package/build/commands/utils/activeProfile.js.map +1 -0
- package/build/commands/utils/browserSessionsApi.js +1 -1
- package/build/commands/utils/browserSessionsApi.js.map +1 -1
- package/build/commands/utils/deviceAuth.js +53 -5
- package/build/commands/utils/deviceAuth.js.map +1 -1
- package/build/commands/utils/environment.js +11 -12
- package/build/commands/utils/environment.js.map +1 -1
- package/build/commands/utils/featureApi.js +30 -30
- package/build/commands/utils/featureApi.js.map +1 -1
- package/build/commands/utils/featureReportGenerator.js +6 -6
- package/build/commands/utils/featureReportGenerator.js.map +1 -1
- package/build/commands/utils/keychain.js +1 -1
- package/build/commands/utils/localAgentInstallationsApi.js +1 -1
- package/build/commands/utils/profileMessages.js +8 -0
- package/build/commands/utils/profileMessages.js.map +1 -0
- package/build/commands/utils/profileSetupBanner.js +167 -0
- package/build/commands/utils/profileSetupBanner.js.map +1 -0
- package/build/commands/utils/settings.js +20 -2
- package/build/commands/utils/settings.js.map +1 -1
- package/build/commands/utils/skills.js +1 -1
- package/build/commands/utils/telemetry.js +254 -0
- package/build/commands/utils/telemetry.js.map +1 -0
- package/build/commands/utils/userApi.js +4 -4
- package/build/commands/utils/userApi.js.map +1 -1
- package/build/commands/verifyFeature.js +771 -526
- package/build/commands/verifyFeature.js.map +1 -1
- package/build/commands/verifyInBrowser.js +1 -1
- package/build/commands/verifyInBrowser.js.map +1 -1
- package/build/skills/ranger/SKILL.md +65 -64
- package/build/skills/ranger/create.md +31 -31
- package/build/skills/ranger/feedback.md +25 -17
- package/build/skills/ranger/start.md +37 -37
- package/build/skills/ranger/verify.md +59 -55
- package/package.json +1 -1
- package/scripts/postinstall.js +1 -1
- package/build/commands/dataMcpServer.js +0 -1
- package/build/commands/dataMcpServer.js.map +0 -1
- package/build/commands/utils/cliSecret.js +0 -1
- package/build/commands/utils/cliSecret.js.map +0 -1
- package/build/skills/bug-bash.md +0 -329
- 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
|
|
30
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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,
|
|
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
|
|
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
|
|
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
|
|
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
|
|
15
|
-
- Create a new feature: \`ranger
|
|
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
|
|
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 (
|
|
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;
|
|
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\
|
|
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;
|
|
1
|
+
{"version":3,"file":"stopHook.js","sourceRoot":"","sources":["../../../src/commands/hooks/stopHook.ts"],"names":[],"mappings":"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"}
|
package/build/commands/index.js
CHANGED
|
@@ -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,
|
|
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"}
|
package/build/commands/login.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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,
|
|
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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"}
|