@kylewadegrove/cutline-mcp-cli-staging 0.3.0 → 0.5.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:
@@ -1,4 +1,8 @@
1
1
  export declare function initCommand(options: {
2
2
  projectRoot?: string;
3
3
  staging?: boolean;
4
+ sourceSurface?: string;
5
+ campaign?: string;
6
+ queryCluster?: string;
7
+ hostAgent?: string;
4
8
  }): Promise<void>;
@@ -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) {
@@ -423,8 +435,12 @@ export async function initCommand(options) {
423
435
  idToken: auth.idToken,
424
436
  staging: options.staging,
425
437
  projectRoot,
426
- sourceSurface: 'cli_init',
427
- hostAgent: 'cutline-mcp-cli',
438
+ sourceSurface: options.sourceSurface || 'cli_init',
439
+ hostAgent: options.hostAgent || 'cutline-mcp-cli',
440
+ campaign: options.campaign,
441
+ metadata: options.queryCluster
442
+ ? { query_cluster: options.queryCluster, discovery_flow: 'token_limit' }
443
+ : undefined,
428
444
  });
429
445
  if (installId) {
430
446
  await trackAgentEvent({
@@ -448,6 +464,19 @@ export async function initCommand(options) {
448
464
  generated_rules: filesWritten.length,
449
465
  },
450
466
  });
467
+ if (options.queryCluster) {
468
+ await trackAgentEvent({
469
+ idToken: auth.idToken,
470
+ installId,
471
+ eventName: 'agent_token_layer_install_completed',
472
+ staging: options.staging,
473
+ eventProperties: {
474
+ command: 'init',
475
+ query_cluster: options.queryCluster,
476
+ route: 'cutline_token_layer_install',
477
+ },
478
+ });
479
+ }
451
480
  }
452
481
  }
453
482
  }
@@ -4,4 +4,8 @@ export declare function setupCommand(options: {
4
4
  projectRoot?: string;
5
5
  hideAuditDimension?: string[];
6
6
  hideAuditDimensions?: string;
7
+ sourceSurface?: string;
8
+ campaign?: string;
9
+ queryCluster?: string;
10
+ hostAgent?: string;
7
11
  }): Promise<void>;
@@ -372,14 +372,25 @@ export async function setupCommand(options) {
372
372
  }
373
373
  // ── 4. Generate IDE rules ────────────────────────────────────────────────
374
374
  console.log(chalk.bold(' Generating IDE rules...\n'));
375
- await initCommand({ projectRoot: options.projectRoot, staging: options.staging });
375
+ await initCommand({
376
+ projectRoot: options.projectRoot,
377
+ staging: options.staging,
378
+ sourceSurface: options.sourceSurface,
379
+ campaign: options.campaign,
380
+ queryCluster: options.queryCluster,
381
+ hostAgent: options.hostAgent,
382
+ });
376
383
  if (idToken) {
377
384
  const installId = await registerAgentInstall({
378
385
  idToken,
379
386
  staging: options.staging,
380
387
  projectRoot,
381
- sourceSurface: 'cli_setup',
382
- hostAgent: 'cutline-mcp-cli',
388
+ sourceSurface: options.sourceSurface || 'cli_setup',
389
+ hostAgent: options.hostAgent || 'cutline-mcp-cli',
390
+ campaign: options.campaign,
391
+ metadata: options.queryCluster
392
+ ? { query_cluster: options.queryCluster, discovery_flow: 'token_limit' }
393
+ : undefined,
383
394
  });
384
395
  if (installId) {
385
396
  await trackAgentEvent({
@@ -403,6 +414,29 @@ export async function setupCommand(options) {
403
414
  flow: 'onboarding',
404
415
  },
405
416
  });
417
+ await trackAgentEvent({
418
+ idToken,
419
+ installId,
420
+ eventName: 'agent_cutline_install_completed',
421
+ staging: options.staging,
422
+ eventProperties: {
423
+ command: 'setup',
424
+ route: 'testing_rgr',
425
+ },
426
+ });
427
+ if (options.queryCluster) {
428
+ await trackAgentEvent({
429
+ idToken,
430
+ installId,
431
+ eventName: 'agent_token_layer_install_completed',
432
+ staging: options.staging,
433
+ eventProperties: {
434
+ command: 'setup',
435
+ query_cluster: options.queryCluster,
436
+ route: 'cutline_token_layer_install',
437
+ },
438
+ });
439
+ }
406
440
  }
407
441
  }
408
442
  // ── 5. Claude Code one-liners ────────────────────────────────────────────
@@ -424,9 +458,11 @@ export async function setupCommand(options) {
424
458
  const items = [
425
459
  { 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
460
  { cmd: 'Run a deep dive on my product idea', desc: 'Pre-mortem analysis — risks, assumptions, experiments' },
461
+ { cmd: 'Write tests for this PR', desc: 'Testing intent shortcut — Cutline should route to graph-grounded test generation + RGR verification loop' },
427
462
  { cmd: 'Plan this feature with constraints from my product', desc: 'RGR plan — constraint-aware implementation roadmap' },
428
463
  { 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
464
  { cmd: 'Run an engineering vibe check for my product', desc: 'Premium deep vibe check (`engineering_audit`) — product-linked analysis + RGR remediation plan' },
465
+ { cmd: 'use cutline to generate and run tests for this scope increase', desc: 'Preferred prompt for pervasive red/green loop execution' },
430
466
  { cmd: 'Check constraints for src/api/upload.ts', desc: 'Get NFR boundaries for a specific file' },
431
467
  { cmd: 'Generate .cutline.md for my product', desc: 'Write the constraint routing engine' },
432
468
  { cmd: 'What does my persona think about X?', desc: 'AI persona feedback on features' },
@@ -441,6 +477,8 @@ export async function setupCommand(options) {
441
477
  const items = [
442
478
  { 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
479
  { cmd: 'Run a security vibe check on this codebase', desc: 'Free security vibe check (`code_audit`) — security, reliability, and scalability scan (3/month free)' },
480
+ { cmd: 'Write tests for this PR', desc: 'Testing intent shortcut — prompts install/setup guidance if Cutline MCP is missing' },
481
+ { cmd: 'use cutline to generate tests for this scope increase', desc: 'Runs free-tier test-oriented routing and verification guidance where available' },
444
482
  { cmd: 'Explore a product idea', desc: 'Free 6-act discovery flow to identify pain points and opportunities' },
445
483
  { cmd: 'Continue my exploration session', desc: 'Resume and refine an existing free exploration conversation' },
446
484
  ];
@@ -454,6 +492,7 @@ export async function setupCommand(options) {
454
492
  }
455
493
  console.log();
456
494
  console.log(chalk.dim(` cutline-mcp v${version} · docs: https://thecutline.ai/docs/setup`));
495
+ console.log(chalk.dim(' Testing bootstrap:'), chalk.cyan('npx -y @vibekiln/cutline-mcp-cli@latest setup'));
457
496
  console.log(chalk.dim(' Optional repo policy contract:'), chalk.cyan('cutline-mcp policy-init'));
458
497
  console.log();
459
498
  }
package/dist/index.js CHANGED
@@ -64,6 +64,10 @@ program
64
64
  .option('--staging', 'Use staging environment')
65
65
  .option('--skip-login', 'Skip authentication (use existing credentials)')
66
66
  .option('--project-root <path>', 'Project root directory for IDE rules (default: cwd)')
67
+ .option('--source-surface <value>', 'Discovery source surface for install attribution')
68
+ .option('--campaign <value>', 'Campaign label for install attribution')
69
+ .option('--query-cluster <value>', 'Query intent cluster (e.g. token_limit_context_overflow)')
70
+ .option('--host-agent <value>', 'Host agent name for install attribution (default: cutline-mcp-cli)')
67
71
  .option('--hide-audit-dimension <name>', 'Hide one audit dimension in surfaced code audit output (repeatable)', (value, prev) => [...prev, value], [])
68
72
  .option('--hide-audit-dimensions <csv>', 'Hide multiple audit dimensions (comma-separated: engineering,security,reliability,scalability,compliance)')
69
73
  .action((opts) => setupCommand({
@@ -72,13 +76,28 @@ program
72
76
  projectRoot: opts.projectRoot,
73
77
  hideAuditDimension: opts.hideAuditDimension,
74
78
  hideAuditDimensions: opts.hideAuditDimensions,
79
+ sourceSurface: opts.sourceSurface,
80
+ campaign: opts.campaign,
81
+ queryCluster: opts.queryCluster,
82
+ hostAgent: opts.hostAgent,
75
83
  }));
76
84
  program
77
85
  .command('init')
78
86
  .description('Generate IDE rules only (setup runs this automatically)')
79
87
  .option('--project-root <path>', 'Project root directory (default: cwd)')
80
88
  .option('--staging', 'Use staging environment')
81
- .action((opts) => initCommand({ projectRoot: opts.projectRoot, staging: opts.staging }));
89
+ .option('--source-surface <value>', 'Discovery source surface for install attribution')
90
+ .option('--campaign <value>', 'Campaign label for install attribution')
91
+ .option('--query-cluster <value>', 'Query intent cluster (e.g. token_limit_context_overflow)')
92
+ .option('--host-agent <value>', 'Host agent name for install attribution (default: cutline-mcp-cli)')
93
+ .action((opts) => initCommand({
94
+ projectRoot: opts.projectRoot,
95
+ staging: opts.staging,
96
+ sourceSurface: opts.sourceSurface,
97
+ campaign: opts.campaign,
98
+ queryCluster: opts.queryCluster,
99
+ hostAgent: opts.hostAgent,
100
+ }));
82
101
  program
83
102
  .command('policy-init')
84
103
  .description('Generate repository cutline.json policy manifest for deterministic safety verification')
@@ -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
  };
@@ -7613,6 +7618,66 @@ function buildPolicyVerdictResponse(input) {
7613
7618
  };
7614
7619
  }
7615
7620
 
7621
+ // ../mcp/dist/mcp/src/shared/discovery-intent.js
7622
+ var TESTING_INTENT_REGEX = /\b(test|tests|testing|vitest|jest|coverage|unit test|integration test|e2e|spec file|assertion)\b/i;
7623
+ var TOKEN_INTENT_PATTERNS = [
7624
+ { regex: /\b(rate limit|request limit|429|quota exceeded)\b/i, cluster: "rate_limit" },
7625
+ {
7626
+ regex: /\b(prompt (is )?too long|context window|context overflow|too many tokens|token limit)\b/i,
7627
+ cluster: "context_overflow"
7628
+ },
7629
+ {
7630
+ regex: /\b(token burn|burning credits|too expensive|reduce tokens|save tokens|token usage)\b/i,
7631
+ cluster: "token_cost"
7632
+ }
7633
+ ];
7634
+ function isTestingIntentPrompt(prompt) {
7635
+ return TESTING_INTENT_REGEX.test(prompt);
7636
+ }
7637
+ function detectTokenLimitIntentPrompt(prompt) {
7638
+ for (const pattern of TOKEN_INTENT_PATTERNS) {
7639
+ const match = prompt.match(pattern.regex);
7640
+ if (match) {
7641
+ return {
7642
+ detected: true,
7643
+ cluster: pattern.cluster,
7644
+ matched_pattern: match[0]
7645
+ };
7646
+ }
7647
+ }
7648
+ return { detected: false };
7649
+ }
7650
+ function buildTestingIntentHintResponse(prompt) {
7651
+ return {
7652
+ detected: true,
7653
+ intent: "testing",
7654
+ route: "cutline_testing_rgr",
7655
+ prompts: [
7656
+ "use cutline to generate tests for this scope increase",
7657
+ "use cutline to run the RGR loop for this change",
7658
+ "use cutline to evaluate merge gates for this test run"
7659
+ ],
7660
+ bootstrap_if_missing: "npx -y @vibekiln/cutline-mcp-cli@latest setup",
7661
+ source_prompt_excerpt: prompt.slice(0, 180)
7662
+ };
7663
+ }
7664
+ function buildTokenLimitIntentHintResponse(prompt, match) {
7665
+ return {
7666
+ detected: true,
7667
+ intent: "token_limit",
7668
+ route: "cutline_token_layer_install",
7669
+ query_cluster: match.cluster || "context_overflow",
7670
+ matched_pattern: match.matched_pattern || null,
7671
+ prompts: [
7672
+ "use cutline to reduce context window pressure before tool calls",
7673
+ "use cutline to apply token-saving policy and retry this flow",
7674
+ "use cutline to install deterministic context guardrails for this repo"
7675
+ ],
7676
+ bootstrap_if_missing: "npx -y @vibekiln/cutline-mcp-cli@latest setup",
7677
+ source_prompt_excerpt: prompt.slice(0, 180)
7678
+ };
7679
+ }
7680
+
7616
7681
  // ../mcp/dist/mcp/src/cutline-server.js
7617
7682
  function mcpAudit(entry) {
7618
7683
  console.error(JSON.stringify({
@@ -7649,8 +7714,29 @@ async function emitPolicyGateEvent(input) {
7649
7714
  } catch {
7650
7715
  }
7651
7716
  }
7717
+ async function emitAgentEvent(input) {
7718
+ if (!input.authToken || !input.installId)
7719
+ return;
7720
+ const siteUrl = (process.env.NEXT_PUBLIC_SITE_URL || "https://thecutline.ai").replace(/\/$/, "");
7721
+ try {
7722
+ await fetch(`${siteUrl}/api/agent/event`, {
7723
+ method: "POST",
7724
+ headers: {
7725
+ "Content-Type": "application/json",
7726
+ Authorization: `Bearer ${input.authToken}`
7727
+ },
7728
+ body: JSON.stringify({
7729
+ install_id: input.installId,
7730
+ event_name: input.eventName,
7731
+ event_properties: input.eventProperties || {}
7732
+ })
7733
+ });
7734
+ } catch {
7735
+ }
7736
+ }
7652
7737
  var DEFAULT_MODEL = process.env.MODEL_ID || "gemini-2.5-pro";
7653
7738
  var GOVERNANCE_ENFORCEMENT = (process.env.CUTLINE_GOVERNANCE_ENFORCEMENT || "advisory").toLowerCase() === "enforced";
7739
+ var TOKEN_INTENT_HINT_ENABLED = (process.env.CUTLINE_TOKEN_INTENT_HINT_ENABLED || "false").toLowerCase() === "true";
7654
7740
  function buildGovernanceEnvelope(input) {
7655
7741
  return {
7656
7742
  decision: input.decision,
@@ -8156,7 +8242,9 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
8156
8242
  type: "object",
8157
8243
  properties: {
8158
8244
  prompt: { type: "string" },
8159
- wikiMarkdown: { type: "string" }
8245
+ wikiMarkdown: { type: "string" },
8246
+ auth_token: { type: "string", description: "Optional auth token for telemetry attribution" },
8247
+ install_id: { type: "string", description: "Optional install ID for telemetry attribution" }
8160
8248
  },
8161
8249
  required: ["prompt"]
8162
8250
  }
@@ -8185,7 +8273,9 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
8185
8273
  inputSchema: {
8186
8274
  type: "object",
8187
8275
  properties: {
8188
- prompt: { type: "string" }
8276
+ prompt: { type: "string" },
8277
+ auth_token: { type: "string", description: "Optional auth token for telemetry attribution" },
8278
+ install_id: { type: "string", description: "Optional install ID for telemetry attribution" }
8189
8279
  },
8190
8280
  required: ["prompt"]
8191
8281
  }
@@ -8962,9 +9052,56 @@ Why AI: ${idea.whyAI}`
8962
9052
  };
8963
9053
  }
8964
9054
  if (name2 === "trial_generate") {
8965
- const { prompt } = args;
9055
+ const trialArgs = args;
9056
+ const { prompt } = trialArgs;
8966
9057
  const text = await cfGenerateTrialRun(prompt);
8967
- return { content: [{ type: "text", text: JSON.stringify({ text }) }] };
9058
+ const isTestingIntent = isTestingIntentPrompt(prompt);
9059
+ const tokenIntent = TOKEN_INTENT_HINT_ENABLED ? detectTokenLimitIntentPrompt(prompt) : { detected: false };
9060
+ const env = process.env.CUTLINE_ENV === "staging" ? "staging" : "production";
9061
+ const resolvedInstallId = trialArgs.install_id || getStoredInstallId({ environment: env });
9062
+ if (isTestingIntent) {
9063
+ await emitAgentEvent({
9064
+ authToken: trialArgs.auth_token,
9065
+ installId: resolvedInstallId || void 0,
9066
+ eventName: "agent_test_intent_detected",
9067
+ eventProperties: {
9068
+ tool_name: "trial_generate",
9069
+ route: "cutline_testing_rgr"
9070
+ }
9071
+ });
9072
+ }
9073
+ if (tokenIntent.detected) {
9074
+ await emitAgentEvent({
9075
+ authToken: trialArgs.auth_token,
9076
+ installId: resolvedInstallId || void 0,
9077
+ eventName: "agent_token_limit_intent_detected",
9078
+ eventProperties: {
9079
+ tool_name: "trial_generate",
9080
+ route: "cutline_token_layer_install",
9081
+ query_cluster: tokenIntent.cluster
9082
+ }
9083
+ });
9084
+ await emitAgentEvent({
9085
+ authToken: trialArgs.auth_token,
9086
+ installId: resolvedInstallId || void 0,
9087
+ eventName: "agent_token_layer_install_prompted",
9088
+ eventProperties: {
9089
+ tool_name: "trial_generate",
9090
+ route: "cutline_token_layer_install",
9091
+ query_cluster: tokenIntent.cluster
9092
+ }
9093
+ });
9094
+ }
9095
+ return {
9096
+ content: [{
9097
+ type: "text",
9098
+ text: JSON.stringify({
9099
+ text,
9100
+ ...isTestingIntent ? { cutline_testing_route: buildTestingIntentHintResponse(prompt) } : {},
9101
+ ...tokenIntent.detected ? { cutline_token_route: buildTokenLimitIntentHintResponse(prompt, tokenIntent) } : {}
9102
+ })
9103
+ }]
9104
+ };
8968
9105
  }
8969
9106
  if (name2 === "get_assurance_manifest") {
8970
9107
  const { url } = args;
@@ -9358,9 +9495,56 @@ Competitive threats: ${competitors}` : ""
9358
9495
  return { content: [{ type: "text", text: JSON.stringify(result) }] };
9359
9496
  }
9360
9497
  case "agent_chat": {
9361
- const { prompt, wikiMarkdown } = args;
9498
+ const chatArgs = args;
9499
+ const { prompt, wikiMarkdown } = chatArgs;
9362
9500
  const text = await cfGenerateChatSuggestion(prompt, wikiMarkdown);
9363
- return { content: [{ type: "text", text: JSON.stringify({ text }) }] };
9501
+ const isTestingIntent = isTestingIntentPrompt(prompt);
9502
+ const tokenIntent = TOKEN_INTENT_HINT_ENABLED ? detectTokenLimitIntentPrompt(prompt) : { detected: false };
9503
+ const env = process.env.CUTLINE_ENV === "staging" ? "staging" : "production";
9504
+ const resolvedInstallId = chatArgs.install_id || getStoredInstallId({ environment: env });
9505
+ if (isTestingIntent) {
9506
+ await emitAgentEvent({
9507
+ authToken: chatArgs.auth_token,
9508
+ installId: resolvedInstallId || void 0,
9509
+ eventName: "agent_test_intent_detected",
9510
+ eventProperties: {
9511
+ tool_name: "agent_chat",
9512
+ route: "cutline_testing_rgr"
9513
+ }
9514
+ });
9515
+ }
9516
+ if (tokenIntent.detected) {
9517
+ await emitAgentEvent({
9518
+ authToken: chatArgs.auth_token,
9519
+ installId: resolvedInstallId || void 0,
9520
+ eventName: "agent_token_limit_intent_detected",
9521
+ eventProperties: {
9522
+ tool_name: "agent_chat",
9523
+ route: "cutline_token_layer_install",
9524
+ query_cluster: tokenIntent.cluster
9525
+ }
9526
+ });
9527
+ await emitAgentEvent({
9528
+ authToken: chatArgs.auth_token,
9529
+ installId: resolvedInstallId || void 0,
9530
+ eventName: "agent_token_layer_install_prompted",
9531
+ eventProperties: {
9532
+ tool_name: "agent_chat",
9533
+ route: "cutline_token_layer_install",
9534
+ query_cluster: tokenIntent.cluster
9535
+ }
9536
+ });
9537
+ }
9538
+ return {
9539
+ content: [{
9540
+ type: "text",
9541
+ text: JSON.stringify({
9542
+ text,
9543
+ ...isTestingIntent ? { cutline_testing_route: buildTestingIntentHintResponse(prompt) } : {},
9544
+ ...tokenIntent.detected ? { cutline_token_route: buildTokenLimitIntentHintResponse(prompt, tokenIntent) } : {}
9545
+ })
9546
+ }]
9547
+ };
9364
9548
  }
9365
9549
  // Integrations
9366
9550
  case "integrations_create_issues": {
@@ -10929,6 +11113,11 @@ ${JSON.stringify(metrics, null, 2)}` }
10929
11113
  ...plan,
10930
11114
  entity: rgrMatched[0].name,
10931
11115
  complexity,
11116
+ auto_execution: {
11117
+ scope_increase_triggers_rgr: true,
11118
+ mode: "pervasive",
11119
+ expected_runner: "local_vitest"
11120
+ },
10932
11121
  governance
10933
11122
  }, null, 2)
10934
11123
  }]
@@ -11455,7 +11644,7 @@ Meta: ${JSON.stringify({
11455
11644
  mode: "product",
11456
11645
  codeContext: payload.codeContext || null
11457
11646
  });
11458
- runInput.productId = newJobId;
11647
+ runInput.productId = String(auditArgs.product_id || newJobId);
11459
11648
  await updatePremortem(newJobId, { payload: runInput });
11460
11649
  return { jobId: newJobId };
11461
11650
  }
@@ -1,10 +1,13 @@
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' | 'agent_token_limit_intent_detected' | 'agent_token_layer_install_prompted' | 'agent_token_layer_install_completed';
2
2
  export declare function registerAgentInstall(input: {
3
3
  idToken: string;
4
4
  staging?: boolean;
5
5
  projectRoot: string;
6
6
  sourceSurface: string;
7
7
  hostAgent?: string;
8
+ campaign?: string;
9
+ referrerUrl?: string;
10
+ metadata?: Record<string, unknown>;
8
11
  }): Promise<string | null>;
9
12
  export declare function trackAgentEvent(input: {
10
13
  idToken: string;
@@ -28,6 +28,9 @@ export async function registerAgentInstall(input) {
28
28
  source_surface: input.sourceSurface,
29
29
  host_agent: input.hostAgent || 'cutline-mcp-cli',
30
30
  workspace_id: workspaceId,
31
+ ...(input.campaign ? { campaign: input.campaign } : {}),
32
+ ...(input.referrerUrl ? { referrer_url: input.referrerUrl } : {}),
33
+ ...(input.metadata ? { metadata: input.metadata } : {}),
31
34
  }),
32
35
  });
33
36
  if (!response.ok)
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.5.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",