@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 +12 -0
- package/dist/commands/init.d.ts +4 -0
- package/dist/commands/init.js +31 -2
- package/dist/commands/setup.d.ts +4 -0
- package/dist/commands/setup.js +42 -3
- package/dist/index.js +20 -1
- package/dist/servers/cutline-server.js +196 -7
- package/dist/utils/agent-funnel.d.ts +4 -1
- package/dist/utils/agent-funnel.js +3 -0
- package/package.json +1 -1
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:
|
package/dist/commands/init.d.ts
CHANGED
package/dist/commands/init.js
CHANGED
|
@@ -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
|
}
|
package/dist/commands/setup.d.ts
CHANGED
package/dist/commands/setup.js
CHANGED
|
@@ -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({
|
|
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
|
-
.
|
|
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
|
|
9055
|
+
const trialArgs = args;
|
|
9056
|
+
const { prompt } = trialArgs;
|
|
8966
9057
|
const text = await cfGenerateTrialRun(prompt);
|
|
8967
|
-
|
|
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
|
|
9498
|
+
const chatArgs = args;
|
|
9499
|
+
const { prompt, wikiMarkdown } = chatArgs;
|
|
9362
9500
|
const text = await cfGenerateChatSuggestion(prompt, wikiMarkdown);
|
|
9363
|
-
|
|
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
|
+
"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",
|