@kylewadegrove/cutline-mcp-cli-staging 0.3.0 → 0.4.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 CHANGED
@@ -35,6 +35,16 @@ cutline-mcp setup
35
35
 
36
36
  Then ask your AI agent: **"use cutline"**
37
37
 
38
+ For test-heavy flows, use the explicit bootstrap + route:
39
+
40
+ ```bash
41
+ npx -y @vibekiln/cutline-mcp-cli@latest setup
42
+ ```
43
+
44
+ Then ask:
45
+ - `Write tests for this PR`
46
+ - `use cutline to generate and run constraint-grounded tests for this scope increase`
47
+
38
48
  Cutline interprets intent and tier:
39
49
  - Natural variants also work: `use cutline to ...`, `using cutline, ...`, `with cutline ...`
40
50
  - Free/default: runs `code_audit` (generic codebase scan)
@@ -185,6 +195,8 @@ The `init` command creates rules that make your AI coding agent follow the Red-G
185
195
  3. **Verify** — Run a code audit to check coverage
186
196
  4. **Complete** — Mark the phase done to update readiness scores
187
197
 
198
+ When the agent detects testing intent (write/generate/validate tests), it should route through Cutline first and, if not configured, prompt the install bootstrap command above before continuing.
199
+
188
200
  ### Compliance Frameworks
189
201
 
190
202
  Cutline auto-detects your stack and loads the appropriate compliance constraints:
@@ -129,6 +129,12 @@ If the user invokes Cutline naturally (for example: **"use cutline"**, **"use cu
129
129
  - Free/default intent: run \`code_audit(project_root)\` (aka "security vibe check")
130
130
  - Premium product-linked intent: run \`engineering_audit(product_id, project_root)\`
131
131
  - Feature implementation intent: run \`rgr_plan(...)\` then \`constraints_auto(...)\`
132
+
133
+ ## Testing Intent Auto-Route
134
+
135
+ If asked to write, generate, validate, or improve tests, route to Cutline first:
136
+ - If Cutline MCP is missing, provide install bootstrap: \`npx -y @vibekiln/cutline-mcp-cli@latest setup\`
137
+ - Then run: \`use cutline to generate and run constraint-grounded tests for this scope increase\`
132
138
  `;
133
139
  }
134
140
  function cursorConstraintsRule(config, tier) {
@@ -219,6 +225,12 @@ If the user invokes Cutline naturally (for example: **"use cutline"**, **"use cu
219
225
  - Free/default intent: \`code_audit(project_root)\` (aka "security vibe check")
220
226
  - Premium product-linked intent: \`engineering_audit(product_id, project_root)\`
221
227
  - Feature implementation intent: \`rgr_plan(...)\` then \`constraints_auto(...)\`
228
+
229
+ ## Testing Intent Auto-Route
230
+
231
+ If asked to write, generate, validate, or improve tests, route to Cutline first:
232
+ - If Cutline MCP is missing, provide install bootstrap: \`npx -y @vibekiln/cutline-mcp-cli@latest setup\`
233
+ - Then run: \`use cutline to generate and run constraint-grounded tests for this scope increase\`
222
234
  `;
223
235
  }
224
236
  function ensureGitignore(projectRoot, patterns) {
@@ -403,6 +403,16 @@ export async function setupCommand(options) {
403
403
  flow: 'onboarding',
404
404
  },
405
405
  });
406
+ await trackAgentEvent({
407
+ idToken,
408
+ installId,
409
+ eventName: 'agent_cutline_install_completed',
410
+ staging: options.staging,
411
+ eventProperties: {
412
+ command: 'setup',
413
+ route: 'testing_rgr',
414
+ },
415
+ });
406
416
  }
407
417
  }
408
418
  // ── 5. Claude Code one-liners ────────────────────────────────────────────
@@ -424,9 +434,11 @@ export async function setupCommand(options) {
424
434
  const items = [
425
435
  { cmd: 'use cutline', desc: 'Magic phrase (also works with "use cutline to...", "using cutline...", "with cutline...") — Cutline infers intent and routes to the right flow' },
426
436
  { cmd: 'Run a deep dive on my product idea', desc: 'Pre-mortem analysis — risks, assumptions, experiments' },
437
+ { cmd: 'Write tests for this PR', desc: 'Testing intent shortcut — Cutline should route to graph-grounded test generation + RGR verification loop' },
427
438
  { cmd: 'Plan this feature with constraints from my product', desc: 'RGR plan — constraint-aware implementation roadmap' },
428
439
  { cmd: 'Run a security vibe check on this codebase', desc: 'Free security vibe check (`code_audit`) — security, reliability, and scalability (generic, not product-linked)' },
429
440
  { cmd: 'Run an engineering vibe check for my product', desc: 'Premium deep vibe check (`engineering_audit`) — product-linked analysis + RGR remediation plan' },
441
+ { cmd: 'use cutline to generate and run tests for this scope increase', desc: 'Preferred prompt for pervasive red/green loop execution' },
430
442
  { cmd: 'Check constraints for src/api/upload.ts', desc: 'Get NFR boundaries for a specific file' },
431
443
  { cmd: 'Generate .cutline.md for my product', desc: 'Write the constraint routing engine' },
432
444
  { cmd: 'What does my persona think about X?', desc: 'AI persona feedback on features' },
@@ -441,6 +453,8 @@ export async function setupCommand(options) {
441
453
  const items = [
442
454
  { cmd: 'use cutline', desc: 'Magic phrase (also works with "use cutline to...", "using cutline...", "with cutline...") — Cutline routes to the highest-value free flow for your intent' },
443
455
  { cmd: 'Run a security vibe check on this codebase', desc: 'Free security vibe check (`code_audit`) — security, reliability, and scalability scan (3/month free)' },
456
+ { cmd: 'Write tests for this PR', desc: 'Testing intent shortcut — prompts install/setup guidance if Cutline MCP is missing' },
457
+ { cmd: 'use cutline to generate tests for this scope increase', desc: 'Runs free-tier test-oriented routing and verification guidance where available' },
444
458
  { cmd: 'Explore a product idea', desc: 'Free 6-act discovery flow to identify pain points and opportunities' },
445
459
  { cmd: 'Continue my exploration session', desc: 'Resume and refine an existing free exploration conversation' },
446
460
  ];
@@ -454,6 +468,7 @@ export async function setupCommand(options) {
454
468
  }
455
469
  console.log();
456
470
  console.log(chalk.dim(` cutline-mcp v${version} · docs: https://thecutline.ai/docs/setup`));
471
+ console.log(chalk.dim(' Testing bootstrap:'), chalk.cyan('npx -y @vibekiln/cutline-mcp-cli@latest setup'));
457
472
  console.log(chalk.dim(' Optional repo policy contract:'), chalk.cyan('cutline-mcp policy-init'));
458
473
  console.log();
459
474
  }
@@ -6596,6 +6596,11 @@ async function handleCodeAudit(args, deps) {
6596
6596
  },
6597
6597
  sensitiveDataCount: scanResult.sensitive_data.fields.length,
6598
6598
  rgrPlan,
6599
+ rgrAutoTrigger: {
6600
+ enabled: true,
6601
+ onScopeIncrease: true,
6602
+ executionMode: "local_vitest"
6603
+ },
6599
6604
  securityGaps: graphAnalysis.securityGaps
6600
6605
  }
6601
6606
  };
@@ -7649,6 +7654,43 @@ async function emitPolicyGateEvent(input) {
7649
7654
  } catch {
7650
7655
  }
7651
7656
  }
7657
+ async function emitAgentEvent(input) {
7658
+ if (!input.authToken || !input.installId)
7659
+ return;
7660
+ const siteUrl = (process.env.NEXT_PUBLIC_SITE_URL || "https://thecutline.ai").replace(/\/$/, "");
7661
+ try {
7662
+ await fetch(`${siteUrl}/api/agent/event`, {
7663
+ method: "POST",
7664
+ headers: {
7665
+ "Content-Type": "application/json",
7666
+ Authorization: `Bearer ${input.authToken}`
7667
+ },
7668
+ body: JSON.stringify({
7669
+ install_id: input.installId,
7670
+ event_name: input.eventName,
7671
+ event_properties: input.eventProperties || {}
7672
+ })
7673
+ });
7674
+ } catch {
7675
+ }
7676
+ }
7677
+ function isTestingIntentPrompt(prompt) {
7678
+ return /\b(test|tests|testing|vitest|jest|coverage|unit test|integration test|e2e|spec file|assertion)\b/i.test(prompt);
7679
+ }
7680
+ function buildTestingIntentHintResponse(prompt) {
7681
+ return {
7682
+ detected: true,
7683
+ intent: "testing",
7684
+ route: "cutline_testing_rgr",
7685
+ prompts: [
7686
+ "use cutline to generate tests for this scope increase",
7687
+ "use cutline to run the RGR loop for this change",
7688
+ "use cutline to evaluate merge gates for this test run"
7689
+ ],
7690
+ bootstrap_if_missing: "npx -y @vibekiln/cutline-mcp-cli@latest setup",
7691
+ source_prompt_excerpt: prompt.slice(0, 180)
7692
+ };
7693
+ }
7652
7694
  var DEFAULT_MODEL = process.env.MODEL_ID || "gemini-2.5-pro";
7653
7695
  var GOVERNANCE_ENFORCEMENT = (process.env.CUTLINE_GOVERNANCE_ENFORCEMENT || "advisory").toLowerCase() === "enforced";
7654
7696
  function buildGovernanceEnvelope(input) {
@@ -8156,7 +8198,9 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
8156
8198
  type: "object",
8157
8199
  properties: {
8158
8200
  prompt: { type: "string" },
8159
- wikiMarkdown: { type: "string" }
8201
+ wikiMarkdown: { type: "string" },
8202
+ auth_token: { type: "string", description: "Optional auth token for telemetry attribution" },
8203
+ install_id: { type: "string", description: "Optional install ID for telemetry attribution" }
8160
8204
  },
8161
8205
  required: ["prompt"]
8162
8206
  }
@@ -8185,7 +8229,9 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
8185
8229
  inputSchema: {
8186
8230
  type: "object",
8187
8231
  properties: {
8188
- prompt: { type: "string" }
8232
+ prompt: { type: "string" },
8233
+ auth_token: { type: "string", description: "Optional auth token for telemetry attribution" },
8234
+ install_id: { type: "string", description: "Optional install ID for telemetry attribution" }
8189
8235
  },
8190
8236
  required: ["prompt"]
8191
8237
  }
@@ -8962,9 +9008,32 @@ Why AI: ${idea.whyAI}`
8962
9008
  };
8963
9009
  }
8964
9010
  if (name2 === "trial_generate") {
8965
- const { prompt } = args;
9011
+ const trialArgs = args;
9012
+ const { prompt } = trialArgs;
8966
9013
  const text = await cfGenerateTrialRun(prompt);
8967
- return { content: [{ type: "text", text: JSON.stringify({ text }) }] };
9014
+ const isTestingIntent = isTestingIntentPrompt(prompt);
9015
+ const env = process.env.CUTLINE_ENV === "staging" ? "staging" : "production";
9016
+ const resolvedInstallId = trialArgs.install_id || getStoredInstallId({ environment: env });
9017
+ if (isTestingIntent) {
9018
+ await emitAgentEvent({
9019
+ authToken: trialArgs.auth_token,
9020
+ installId: resolvedInstallId || void 0,
9021
+ eventName: "agent_test_intent_detected",
9022
+ eventProperties: {
9023
+ tool_name: "trial_generate",
9024
+ route: "cutline_testing_rgr"
9025
+ }
9026
+ });
9027
+ }
9028
+ return {
9029
+ content: [{
9030
+ type: "text",
9031
+ text: JSON.stringify({
9032
+ text,
9033
+ ...isTestingIntent ? { cutline_testing_route: buildTestingIntentHintResponse(prompt) } : {}
9034
+ })
9035
+ }]
9036
+ };
8968
9037
  }
8969
9038
  if (name2 === "get_assurance_manifest") {
8970
9039
  const { url } = args;
@@ -9358,9 +9427,32 @@ Competitive threats: ${competitors}` : ""
9358
9427
  return { content: [{ type: "text", text: JSON.stringify(result) }] };
9359
9428
  }
9360
9429
  case "agent_chat": {
9361
- const { prompt, wikiMarkdown } = args;
9430
+ const chatArgs = args;
9431
+ const { prompt, wikiMarkdown } = chatArgs;
9362
9432
  const text = await cfGenerateChatSuggestion(prompt, wikiMarkdown);
9363
- return { content: [{ type: "text", text: JSON.stringify({ text }) }] };
9433
+ const isTestingIntent = isTestingIntentPrompt(prompt);
9434
+ const env = process.env.CUTLINE_ENV === "staging" ? "staging" : "production";
9435
+ const resolvedInstallId = chatArgs.install_id || getStoredInstallId({ environment: env });
9436
+ if (isTestingIntent) {
9437
+ await emitAgentEvent({
9438
+ authToken: chatArgs.auth_token,
9439
+ installId: resolvedInstallId || void 0,
9440
+ eventName: "agent_test_intent_detected",
9441
+ eventProperties: {
9442
+ tool_name: "agent_chat",
9443
+ route: "cutline_testing_rgr"
9444
+ }
9445
+ });
9446
+ }
9447
+ return {
9448
+ content: [{
9449
+ type: "text",
9450
+ text: JSON.stringify({
9451
+ text,
9452
+ ...isTestingIntent ? { cutline_testing_route: buildTestingIntentHintResponse(prompt) } : {}
9453
+ })
9454
+ }]
9455
+ };
9364
9456
  }
9365
9457
  // Integrations
9366
9458
  case "integrations_create_issues": {
@@ -10929,6 +11021,11 @@ ${JSON.stringify(metrics, null, 2)}` }
10929
11021
  ...plan,
10930
11022
  entity: rgrMatched[0].name,
10931
11023
  complexity,
11024
+ auto_execution: {
11025
+ scope_increase_triggers_rgr: true,
11026
+ mode: "pervasive",
11027
+ expected_runner: "local_vitest"
11028
+ },
10932
11029
  governance
10933
11030
  }, null, 2)
10934
11031
  }]
@@ -11455,7 +11552,7 @@ Meta: ${JSON.stringify({
11455
11552
  mode: "product",
11456
11553
  codeContext: payload.codeContext || null
11457
11554
  });
11458
- runInput.productId = newJobId;
11555
+ runInput.productId = String(auditArgs.product_id || newJobId);
11459
11556
  await updatePremortem(newJobId, { payload: runInput });
11460
11557
  return { jobId: newJobId };
11461
11558
  }
@@ -1,4 +1,4 @@
1
- type AgentEventName = 'install_completed' | 'first_tool_call_success' | 'tool_call_failed' | 'heartbeat' | 'policy_gate_passed' | 'policy_gate_blocked' | 'upgrade_clicked' | 'upgrade_completed';
1
+ type AgentEventName = 'install_completed' | 'first_tool_call_success' | 'tool_call_failed' | 'heartbeat' | 'policy_gate_passed' | 'policy_gate_blocked' | 'upgrade_clicked' | 'upgrade_completed' | 'agent_test_intent_detected' | 'agent_cutline_install_prompted' | 'agent_cutline_install_completed' | 'agent_first_rgr_test_call_success';
2
2
  export declare function registerAgentInstall(input: {
3
3
  idToken: string;
4
4
  staging?: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kylewadegrove/cutline-mcp-cli-staging",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "CLI and MCP servers for Cutline — authenticate, then run constraint-aware MCP servers in Cursor or any MCP client.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",